BUSINESS QUESTIONS: Note: ignore the fact there is no question 1,
this is due to a formatting error 2. a) Is there are a trend in injuries
By Region, and is there different peaks of times of year per region? b)
Analysis on the types of animals that are injured, this also by Region –
is there a species that is more liable to injury in certain regions? -
(cat/dog by region) c) What is the outcome? Does this differ by
region?
- Total call volume for complaint calls: How has this trended over
time?
- Is there a particular animal being called about the most?
- Do particular suburbs have different type of complaint calls? Do
they call about different animals? ((MAKE A LEAFLET MAP FOR THIS!))
- Business Intelligence – using the insights you have found, can you
predict how this might look for the upcoming year?
library(tidyverse)
library(tsibble)
library(forecast)
source("cleaning_script.R")
Rows: 31330 Columns: 7── Column specification ────────────────────────────────────────────────────────────────
Delimiter: ","
chr (6): nature, animal_type, category, suburb, date_range, city
lgl (1): responsible_office
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.Warning: Expected 2 pieces. Missing pieces filled with `NA` in 5643 rows [7, 11, 12, 18, 19, 25, 27, 29, 30, 31, 39, 44, 52, 54, 66, 67, 74, 75, 78, 81, ...].Rows: 42413 Columns: 5── Column specification ────────────────────────────────────────────────────────────────
Delimiter: ","
chr (5): Animal Type, Complaint Type, Date Received, Suburb, Electoral Division
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.Rows: 664 Columns: 12── Column specification ────────────────────────────────────────────────────────────────
Delimiter: ","
chr (2): animal_type, outcome
dbl (10): year, ACT, NSW, NT, QLD, SA, TAS, VIC, WA, Total
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Note; summer in Australia seasons: Summer: December - February
Autumn: March - May Winter: June - August Spring: September -
November
also: The ‘wet season’ in Australia’s North: November - April
https://www.mdpi.com/2076-2615/8/7/100 will useful
reading for later, talk about the need to reduce euthanasia or similar
and the effect this has on people
Intro: Introduce the point of the talk, talk about Australian RSPCA,
talk about how the data was gathered (using the information from the
websites), the PURPOSE of this investigation (which is to help the RSPCA
know which areas/animals to focus their efforts on), as I’m introducing
the datasets I can introduce the two different cities. First, we can
talk a short bit about Australia as a whole, it’s climate, the kind of
animals etc. The point here is to really set the scene before diving too
deep into facts and figures, as especially a non-technical audience this
will help keep them engaged and make a more holistic presentation. In my
opinion, it’s always good to zoom out and see the big picture, rather
than getting lost in the myopia of some csv files.
Townsville Intro: Townsville is a city on the north-eastern coast of
Queensland, Australia. With a population of 180,820 as of June 2018, it
is the largest settlement in North Queensland; it is unofficially
considered its capital. [note: put a map of Australia with Queensland
and Townsville highlighted here. Talk a little bit about the population
density, urbanisation, climate, types of animals that are common here
etc. Show some photos of the area too]
Brisbane Intro: Exact same as above
3.
- Total call volume for complaint calls: How has this trended over
time?
First, let’s look at the Townsville animal complaints.
animal_complaints %>%
group_by(date_received) %>%
summarise(count = n()) %>%
ggplot(aes(x = date_received, y = count)) +
geom_line() +
scale_x_date(date_breaks = "6 months", date_labels = "%b-%y")

This shows some seasonality and also an increase then a decline. Each
summer (in December) the calls are much lower, rising again each Winter.
Using geom_smooth, we get:
animal_complaints %>%
group_by(date_received) %>%
summarise(count = n()) %>%
ggplot(aes(x = date_received, y = count)) +
geom_smooth() +
geom_point() +
scale_x_date(date_breaks = "1 year", date_labels = "%y")

This shows a bit more clearly the general trend of call volume. From
2014 it steadily rises, peaking in 2017. Afterwards, it steadily
declines to only slightly higher than where it started. It would be very
difficult to say whether this trend will continue downward, go upward or
stay relatively flat.
Note; if we have time or if it’s helpful, we will fix this graph so
that quarters are properly displayed.
brisbane_complaints %>%
group_by(date) %>%
summarise(count = n()) %>%
ggplot(aes(x = date, y = count)) +
geom_point() +
geom_line() +
scale_x_date(date_breaks = "3 months", date_labels = "%y")

Again, we see the seasonality of winter having more calls. The fact
this is in both Brisbane and Townsville suggests a fairly general
trend.
brisbane_complaints %>%
group_by(date) %>%
summarise(count = n()) %>%
ggplot(aes(x = date, y = count)) +
geom_point() +
geom_smooth() +
scale_x_date(date_breaks = "1 year", date_labels = "20%y")

Other than declining a little over 2016, the number of calls sees a
slow but steady increase towards 2020, being thousands more than it was
in 2016 and 2017. So, the general trend is that the RSPCA are getting
more complaints as time goes on. Now, this does not necessarily mean the
line will continue to go up. We are also missing Q3 from 2016 so this
skews the curve a little
3.b) Is there a particular animal being called about the most?
animal_complaints %>%
group_by(animal_type) %>%
ggplot(aes(x = animal_type)) +
geom_bar()

The number of calls about dogs dwarf those about cats hugely. Let’s
look at specific numbers:
animal_complaints %>%
group_by(animal_type) %>%
count() %>%
summarise(n, 4094 / 38319)
So cats account for only 10% of the calls dogs do for Townsville!
Let’s look at Brisbane:
brisbane_complaints %>%
group_by(type_of_animal) %>%
count()
brisbane_complaints %>%
group_by(type_of_animal) %>%
ggplot(aes(x = type_of_animal)) +
geom_bar()

We have a lot more animal types here that we don’t in the previous
data. We also have many calls about Attacks with no animal specified,
many of which it is very likely they were involving dogs. However, we
can’t say this for sure.
So that makes
4745 / 13334 # cats are 35% of the calls compared to dogs
[1] 0.3558572
# all other animals divided by dogs, leaving out unspecified (which we believe potentially contain a high proportion of dogs)
9457 / 13349
[1] 0.7084426
Most of the other animals have very small counts, interestingly foxes
seem to make up a decent proportion of the calls regarding wild
animals.
To answer the question however, it’s mainly dogs and cats, and
especially dogs. Dogs are being called about more than any of the other
animals combined (if we leave Unspecified to the side)
(Attack refers to the initial description of the complaint)
3. c) Do particular suburbs have different type of complaint calls?
Do they call about different animals?
OK, so this one is difficult simply for the fact there is a huge
amount of suburbs.
brisbane_complaints %>%
group_by(suburb) %>%
count()
# There is 192 suburbs! Certainly using a fill on a graph is not gonna work, neither is putting them on the x-axis on a bar graph.
animal_complaints %>%
group_by(suburb) %>%
count()
# 85 suburbs for Townsville
animal_complaints %>%
group_by(electoral_division) %>%
count()
# also 11 electoral divisions. Could we look at suburbs one electoral division at a time? Possibly
Idea: What about using leaflet to visualise types of complaint calls
on a map?
This is more feasible with the Townsville datasets, as it has less
suburbs and only 6 types of complaints. It may be necessary to try and
wrangle the Brisbane data a little further to narrow down categories
(for both type_of_animal and complaint_type)
FOR TOWNSVILLE WE HAVE: 85 different suburbs 6 complaint types 2
animal types
We want to break it down by suburb and complaint type, and then by
suburb and animal type
animal_complaints %>%
ggplot(aes(x = suburb, fill = animal_type)) +
geom_bar(position = "fill") +
coord_flip() +
scale_x_discrete(guide = guide_axis(n.dodge = 5))

animal_complaints %>%
ggplot(aes(x = suburb, fill =complaint_type)) +
geom_bar(position = "fill")

#coord_flip() +
#scale_x_discrete(guide = guide_axis(n.dodge = 5))
The challenge again, is having too many suburbs that we can’t get any
useful information out of the graphs
animal_complaints %>%
group_by(suburb) %>%
count(sort = TRUE)
# let's drop any suburbs with less than 200 cases
animal_complaints %>%
group_by(suburb) %>%
summarise(count = n(), animal_type) %>%
filter(count >= 500) %>%
ggplot(aes(x = suburb, y = count, fill = animal_type)) +
geom_col() +
coord_flip()
`summarise()` has grouped output by 'suburb'. You can override using the `.groups` argument.

The highest count by quite a large margin is unallocated to a
specific suburb.
animal_complaints %>%
group_by(suburb) %>%
summarise(count = n(), animal_type) %>%
filter(count >= 500) %>%
ggplot(aes(x = suburb, y = count, fill = animal_type)) +
geom_col(position = "fill") +
coord_flip()
`summarise()` has grouped output by 'suburb'. You can override using the `.groups` argument.

At a glance, there’s no big difference on animal types. All the
suburbs have a large majority of dogs. Could we do a hypothesis test to
see if there is a statistically significant difference?
animal_complaints %>%
group_by(suburb) %>%
summarise(count = n(), animal_type) %>%
filter(count < 500 & count > 100) %>%
ggplot(aes(x = suburb, y = count, fill = animal_type)) +
geom_col(position = "fill") +
coord_flip()
`summarise()` has grouped output by 'suburb'. You can override using the `.groups` argument.

Looking at the lower end of the population, we see an outlier.
Townsville City has way more cats than any of the other suburbs. In
fact, it’s almost 50/50!
Now still looking at the Townsville dataset, we’ll break it down by
complaint type:
animal_complaints %>%
group_by(suburb) %>%
summarise(count = n(), complaint_type) %>%
filter(count >= 500 & count <= 4000) %>%
ggplot(aes(x = suburb, y = count, fill = complaint_type)) +
geom_col(position = "fill") +
coord_flip()
`summarise()` has grouped output by 'suburb'. You can override using the `.groups` argument.

Now for the lower end of the count:
animal_complaints %>%
group_by(suburb) %>%
summarise(count = n(), complaint_type) %>%
filter(count < 500 & count > 50) %>%
ggplot(aes(x = suburb, y = count, fill = complaint_type)) +
geom_col(position = "fill") +
coord_flip()
`summarise()` has grouped output by 'suburb'. You can override using the `.groups` argument.

I’m not sure much can be gleamed with so many complaint_types. Let’s
try focusing more specifically.
One thing to note here, is the vast variation in tolerance for noise.
Most categories are consistent except this one. Cluden for example has a
small percentage of noise complaints,while Bohle Plains has a huge
percentage. This requires more investigation to figure out the root
cause of this:
animal_complaints %>%
group_by(suburb) %>%
summarise(count = n(), complaint_type) %>%
filter(count >= 500) %>%
filter(complaint_type == "Noise" | (complaint_type == "Attack")) %>%
ggplot(aes(x = suburb, y = count, fill = complaint_type)) +
geom_col(position = "fill") +
coord_flip()
`summarise()` has grouped output by 'suburb'. You can override using the `.groups` argument.

animal_complaints %>%
group_by(suburb) %>%
summarise(count = n(), complaint_type) %>%
filter(count >= 500) %>%
filter(complaint_type == "Noise" | (complaint_type == "Aggressive Animal")) %>%
ggplot(aes(x = suburb, y = count, fill = complaint_type)) +
geom_col(position = "fill") +
coord_flip()
`summarise()` has grouped output by 'suburb'. You can override using the `.groups` argument.

animal_complaints %>%
group_by(suburb) %>%
summarise(count = n(), complaint_type) %>%
filter(count >= 500) %>%
filter(complaint_type == "Wandering" | (complaint_type == "Aggressive Animal")) %>%
ggplot(aes(x = suburb, y = count, fill = complaint_type)) +
geom_col(position = "fill") +
coord_flip()
`summarise()` has grouped output by 'suburb'. You can override using the `.groups` argument.

animal_complaints %>%
group_by(suburb) %>%
summarise(count = n(), complaint_type) %>%
filter(count >= 500) %>%
filter(complaint_type == "Enclosure" | (complaint_type == "Noise")) %>%
ggplot(aes(x = suburb, y = count, fill = complaint_type)) +
geom_col(position = "fill") +
coord_flip()
`summarise()` has grouped output by 'suburb'. You can override using the `.groups` argument.

For the less than 500 greater than 50 groups:
animal_complaints %>%
group_by(suburb) %>%
summarise(count = n(), complaint_type) %>%
filter(count < 500 & count > 100) %>%
filter(complaint_type == "Noise" | (complaint_type == "Attack")) %>%
ggplot(aes(x = suburb, y = count, fill = complaint_type)) +
geom_col(position = "fill") +
coord_flip()
`summarise()` has grouped output by 'suburb'. You can override using the `.groups` argument.

animal_complaints %>%
group_by(suburb) %>%
summarise(count = n(), complaint_type) %>%
filter(count < 500 & count > 100) %>%
filter(complaint_type == "Noise" | (complaint_type == "Aggressive Animal")) %>%
ggplot(aes(x = suburb, y = count, fill = complaint_type)) +
geom_col(position = "fill") +
coord_flip()
`summarise()` has grouped output by 'suburb'. You can override using the `.groups` argument.

animal_complaints %>%
group_by(suburb) %>%
summarise(count = n(), complaint_type) %>%
filter(count < 500 & count > 100) %>%
filter(complaint_type == "Wandering" | (complaint_type == "Aggressive Animal")) %>%
ggplot(aes(x = suburb, y = count, fill = complaint_type)) +
geom_col(position = "fill") +
coord_flip()
`summarise()` has grouped output by 'suburb'. You can override using the `.groups` argument.

animal_complaints %>%
group_by(suburb) %>%
summarise(count = n(), complaint_type) %>%
filter(count < 500 & count > 100) %>%
#filter(complaint_type == "Enclosure" | (complaint_type == "Noise")) %>%
ggplot(aes(x = suburb, y = count, fill = complaint_type)) +
geom_col(position = "fill") +
coord_flip() +
facet_wrap(~ suburb)
`summarise()` has grouped output by 'suburb'. You can override using the `.groups` argument.

animal_complaints %>%
group_by(suburb) %>%
summarise(count = n(), complaint_type, animal_type) %>%
filter(count < 500 & count > 100) %>%
ggplot(aes(x = complaint_type, y = count, fill = complaint_type)) +
geom_col() +
facet_wrap(~ suburb)
`summarise()` has grouped output by 'suburb'. You can override using the `.groups` argument.

From this graph, we can see that Hyde Park has a disproportionate
amount of private impounds, while Bohle plains has more noise
complaints.
Potential hypothesis test:
That the level of private impounds in Hyde Park being greater is
statistically significant.
That the level of noise in Bohle Plains being greater is
statistically significant.
animal_complaints %>%
group_by(suburb) %>%
count() %>%
filter(n < 500 & n > 100)
Let’s look at the suburbs with much higher complaints now:
animal_complaints %>%
group_by(suburb) %>%
summarise(count = n(), complaint_type, animal_type) %>%
filter(count >= 500 & count <4000) %>%
ggplot(aes(x = complaint_type, y = count, fill = complaint_type)) +
geom_col() +
facet_wrap(~ suburb)
`summarise()` has grouped output by 'suburb'. You can override using the `.groups` argument.

2. a) Are there any major differences between regions?
How do the animal outcomes differ over time?
Are there any noticeable anomalies in the data?
It’s impossible to say if there’s different peaks of times of yer per
region, as we only have the data for the year as a whole. Unless we look
at Suburb rather than region, and break this down by time. However, I
think it’d be good to use the general Autralia (nationwide) data.
Proportions overall by region and by outcome. We can see that in
general, regions have pretty similar proportions across all outcomes.
This won’t be the case for every year though and trends over time,
that’s the more interesting stuff.

This is the same thing as before, but for animal type. Same as
before, not much discernible difference between the regions.

Next is just the sum ocurrences. We can see the regions that have way
more animals injured/taken in by the RSPCA. This could be a population
thing, maybe these regions just have more wildlife populations etc., or
even a bigger RSPCA presence leading to more cases.

So, this is the data across time (from 1999-2018), with time on the
x-axis and number of occurences on the y. Faceted into graphs based on
outcome, with the coloured lines representing different regions.

What can we say about this? Well, QLD has had their transfers go way
up since about 2009, and in general looks like an increase in cases for
them. NSW had a big spike of Currently In Care around 2004.
Euthanisation in general seems to be falling out of favour (which is
actually true, the RSPCA tries to do it less for various reasons, one
actually being the mental health of the staff and another being lots of
euthanisations leads to a negative perception of animal shelters)
Exact same as before, but faceted on animal type rather than
outcome.

QLD has had a lot more wildlife cases, steadily climbing since about
2006. NSW has had a big drop in cats recently. Dogs too. Horses have
gone up every region it looks like. NT has had a huge spike in cats from
2015-2016.
This one has the same x and y, but is faceted based on region. The
coloured lines now represent the outcomes.

WA in 2006 had a big increase in euthanizations. VIC has had theirs
steadily decreasing over time, this is reflected also in NSW, TAS and
ACT.
Same as before with faceting based on region, but now the coloured
lines represent the type of animal the RSPCA is dealing with.

NT has had a big spike in dogs and cats in recent years. WA had a big
spike in wildlife in 2005, corresponding with their spike in
euthanizations - common sense and domain knowledge tell us these are
likely highly correlated. VIC’s numbers in general seem to be decreasing
over time.
Looking now specifically at euthanizations, faceted by region with
the lines representing euthanizations.

Now we no longer facet by region.




OK so cats and dogs have way less euthanisations. Wildlife has gone
way up! Horses are too small a sample to be meaningful. Other animals
have spiked then decreased.

Looking at rehomes to euthanisations, we see cats have an upward
trend with less euthanisations and more rehomes, with dogs, both have
gone down. Perhaps with dogs there’s a confounding factor. In fact, it
seems like the RSPCA is dealing with less dogs in general.



Euthanizations for wildlife have overall gone up. Queensland is
skewing the data, they’ve euthanized way more! Is this necessarily a bad
thing? It could indicate a bigger RSPCA presence in the area, and more
vigilance in regards to controlling the wildlife.
General thoughts:
big change in 2006 for WA; cyclone Emma March 2006 could’ve released
many wild animals leading to high euthanizations (this for 2.c)
different territories have different approaches;
4. Business Intelligence – using the insights you have found, can
you predict how this might look for the upcoming year?
animal_outcomes %>%
drop_na() %>%
group_by(region, outcome, year) %>%
summarize(total_injuries = sum(number_of_occurences)) %>%
ungroup() %>%
filter(outcome == "Euthanized") %>%
ggplot(aes(x = year, y = total_injuries, color = outcome)) +
geom_line() +
facet_wrap(~region, scales = "free_y") +
labs(x = "Date", y = "Number of injuries", color = "Outcome")
`summarise()` has grouped output by 'region', 'outcome'. You can override using the `.groups` argument.

Next attempt for a model
I want to predict the total cases for Australia. We won’t break it
down by region. So first, let’s get our summary statistics and put it in
a new variable:
animal_outcomes %>%
drop_na() %>%
group_by(outcome, animal_type, year, region) %>%
summarize(total_injuries = sum(number_of_occurences)) %>%
ungroup() %>%
filter(animal_type == "Cats" & outcome == "Euthanized") %>%
ggplot(aes(x = year, y = total_injuries, color = outcome)) +
geom_line() +
facet_wrap(~region, scales = "free_y") +
labs(x = "Date", y = "Number of injuries", color = "Outcome", title = "Cats")
`summarise()` has grouped output by 'outcome', 'animal_type', 'year'. You can override using the `.groups` argument.

animal_outcomes %>%
drop_na() %>%
group_by(outcome, animal_type, year) %>%
summarize(total_injuries = sum(number_of_occurences)) %>%
ungroup() %>%
filter(animal_type == "Cats" & outcome == "Euthanized") %>%
ggplot(aes(x = year, y = total_injuries, color = outcome)) +
geom_line() +
#facet_wrap(~region, scales = "free_y") +
labs(x = "Date", y = "Number of injuries", color = "Outcome", title = "Cats")
`summarise()` has grouped output by 'outcome', 'animal_type'. You can override using the `.groups` argument.

wildlife_tsbl <- animal_outcomes %>%
drop_na() %>%
filter(animal_type == "Cats" & outcome == "Euthanized") %>%
group_by(year) %>%
summarise(total_euth = sum(number_of_occurences)) %>%
ungroup() %>%
as_tsibble(key = year, index = total_euth)
# Fit ARIMA model
wildlife_arima <- wildlife_tsbl %>%
model(total_euth = ARIMA(total_euth))
Warning: 20 errors (1 unique) encountered for total_euth
[20] attempt to select less than one element in get1index
# Generate forecasts
wildlife_forecast <- wildlife_tsbl %>%
model(ARIMA(total_euth)) %>%
forecast(h = 36)
Error in FUN(X[[i]], ...) : object 'total_euth' not found
library(tidyverse)
library(fable)
library(tsibble)
library(tsibbledata)
# We also need to use the "urca" package to be able to use the ARIMA model
library(urca)
library(tsibble)
library(fable)
wildlife_tsbl <- animal_outcomes %>%
drop_na() %>%
filter(animal_type == "Cats" & outcome == "Euthanized") %>%
group_by(year) %>%
summarise(total_euth = sum(number_of_occurences)) %>%
ungroup() %>%
mutate(date = year %>% as.Date(paste0("-01-01"))) %>%
as_tsibble(key = year, index = date)
wildlife_arima <- wildlife_tsbl %>%
model(ARIMA(total_euth))
wildlife_forecast <- wildlife_arima %>%
forecast(h = 36)
wildlife_forecast
NA
NA
wildlife_forecast %>%
autoplot() +
scale_y_continuous(limits = c(0, max(wildlife_tsbl$total_euth, na.rm = TRUE) * 1.2))

library(fable)
library(tsibbledata)
library(dplyr)
library(ggplot2)
# Create tsibble
wildlife_tsbl <- animal_outcomes %>%
drop_na() %>%
filter(animal_type == "Cats" & outcome == "Euthanized") %>%
group_by(year) %>%
summarise(total_euth = sum(number_of_occurences)) %>%
ungroup() %>%
as_tsibble(index = year)
# Fit ARIMA model
wildlife_arima <- wildlife_tsbl %>%
model(ARIMA(total_euth))
Warning: 1 error encountered for ARIMA(total_euth)
[1] .data contains implicit gaps in time. You should check your data and convert implicit gaps into explicit missing values using `tsibble::fill_gaps()` if required.
# Generate forecasts
wildlife_fcst <- wildlife_arima %>%
forecast(h = 36)
# Add source column to forecast
wildlife_fcst %>%
mutate(source = "forecast") %>%
select(source, year, .mean) %>%
bind_rows(wildlife_tsbl %>% as_tibble() %>% mutate(source = "actual")) %>%
# Plot the actuals and forecasts
ggplot(aes(x = year, y = .mean, color = source)) +
geom_line() +
labs(y = "Total Euthanized Cats") +
scale_color_manual(values = c("actual" = "black", "forecast" = "red")) +
theme_minimal()
Error in `build_fable()`:
! Can't subset columns that don't exist.
✖ Column `total_euth` doesn't exist.
Backtrace:
1. ... %>% ggplot(aes(x = year, y = .mean, color = source))
6. fabletools:::select.fbl_ts(., source, year, .mean)
7. fabletools:::restore_fable(res, .data)
8. fabletools:::build_fable(data, response = response_vars(template), distribution = !!distribution_var(template))
wildlife_ts
Time Series:
Start = 1
End = 20
Frequency = 1
[1] 31202 32901 31009 30449 35934 31941 37010 33343 42731 39495 38642 37177 24651 19464
[15] 15491 17398 16205 14563 12610 11740
library(tsibble)
library(fable)
# Convert ts object to tsibble
wildlife_tsbl <- as_tsibble(wildlife_ts, index = "year")
# Fit ARIMA model to tsibble
wildlife_arima <- wildlife_tsbl %>%
model(ARIMA(value))
# Generate forecasts
wildlife_forecast <- wildlife_arima %>%
forecast(h = 36)
# Convert forecast to a tsibble
wildlife_fcst <- as_tsibble(wildlife_forecast, key = "year")
# Plot the forecast
wildlife_fcst %>%
ggplot(aes(x = year, y = .mean, color = source)) +
geom_line()
Error in `geom_line()`:
! Problem while computing aesthetics.
ℹ Error occurred in the 1st layer.
Caused by error in `compute_aesthetics()`:
! Aesthetics are not valid data columns.
✖ The following aesthetics are invalid:
✖ `x = NULL`
✖ `colour = NULL`
ℹ Did you mistype the name of a data column or forget to add `after_stat()`?
Backtrace:
1. base (local) `<fn>`(x)
2. ggplot2:::print.ggplot(x)
4. ggplot2:::ggplot_build.ggplot(x)
5. ggplot2:::by_layer(...)
12. ggplot2 (local) f(l = layers[[i]], d = data[[i]])
13. l$compute_aesthetics(d, plot)
14. ggplot2 (local) compute_aesthetics(..., self = self)

library(tsibble)
library(fable)
library(ggplot2)
# Convert ts object to tsibble
wildlife_tsbl <- as_tsibble(wildlife_ts, index = "year")
# Fit ARIMA model to tsibble
wildlife_arima <- wildlife_tsbl %>%
model(ARIMA(value))
# Generate forecasts
wildlife_forecast <- wildlife_arima %>%
forecast(h = 36)
# Convert forecast to a tsibble
wildlife_fcst <- as_tsibble(wildlife_forecast, key = "year")
# Plot the forecast
wildlife_fcst %>%
ggplot(aes(x = index, y = .mean, color = .model)) +
geom_line()

NA
NA
names(wildlife_fcst)
[1] ".model" "index" "value" ".mean"
# grouping the data and creating a variable
animal_complaints_grouped <- animal_complaints %>%
group_by(date_received) %>%
summarise(count = n()) %>%
arrange(date_received)
myts <- ts(animal_complaints_grouped$count, frequency = 12, start = c(year(animal_complaints_grouped$date_received[1]), month(animal_complaints_grouped$date_received[1])))
myforecast <- forecast(auto.arima(myts), h = 24)
Error in switch(names(interval), day = "days", hour = "hours", minute = "mins", :
EXPR must be a length 1 vector
myts_forecast <- function(myts, h, interval) {
library(forecast)
# Set the appropriate time interval for the forecast horizon
interval <- switch(interval,
"day" = "days",
"hour" = "hours",
"minute" = "mins",
"second" = "secs")
# Create the forecast
myforecast <- forecast(myts, h = 24, level = c(80, 95),
xreg = mydummies,
lambda = NULL, biasadj = TRUE,
fan = FALSE,
interval = "week")
# Print the forecast table
print(myforecast)
# Plot the forecast
autoplot(myforecast)
}
print(interval)
function (start = NULL, end = NULL, tzone = tz(start))
{
if (is.character(start) && is.null(end)) {
return(parse_interval(start, tzone))
}
if (length(start) == 0 || length(end) == 0) {
if (is.null(start) && missing(tzone)) {
tzone <- "UTC"
}
start <- POSIXct(tz = tzone)
return(new("Interval", numeric(), start = start, tzone = tzone))
}
if (is.Date(start))
start <- date_to_posix(start)
if (is.Date(end))
end <- date_to_posix(end)
force(tzone)
start <- as_POSIXct(start, tzone)
end <- as_POSIXct(end, tzone)
span <- as.numeric(end) - as.numeric(start)
starts <- start + rep(0, length(span))
if (tzone != tz(starts))
starts <- with_tz(starts, tzone)
new("Interval", span, start = starts, tzone = tzone)
}
<bytecode: 0x7fa7b16da468>
<environment: namespace:lubridate>
print(class(interval))
[1] "function"
print(length(interval))
[1] 1
# Create a sequence of dates for the next 24 months
dates <- seq(as.Date("2023-03-01"), by = "month", length.out = 24)
# Create a time series object with random values for demonstration purposes
values <- rnorm(24)
myts <- ts(values, start = c(year(dates[1]), month(dates[1])), frequency = 12)
# Plot the time series
plot(myts)

# Forecast the next 24 months
library(forecast)
myforecast <- forecast(myts, h = 24)
Error in UseMethod("forecast") :
no applicable method for 'forecast' applied to an object of class "ts"
Another, FINAL attempt
This is quite difficult indeed. Let’s try go slowly using the notes,
build it bit by bit.
So all we wanna do, is plot the next few years, and see what it will
look like on the graph. Nothing needs to be too fancy. We will keep it
simple, create a simple model. Then plot this. OK.
So first, it needs to be tsibble.
It has now been converted to a tsibble, with date_received as the
index. As it contains only a single time series, a key should not be
necessary.
library(tidyverse)
library(fable)
library(tsibble)
library(tsibbledata)
# We also need to use the "urca" package to be able to use the ARIMA model
library(urca)
We load in all packages just to be 100% sure they are loaded.
# next, we will use autoplot
autoplot(animal_complaints_tsibble)
Plot variable not specified, automatically selected `.vars = count`

Our data is there. Now, we will fit a model.
library(purrr)
fit <- animal_complaints_tsibble %>%
model(
snaive = SNAIVE(count),
mean_model = MEAN(count),
arima = ARIMA(count)
)
fit
# fit %>%
# dmap(unlist)
Here is our mable, also called model table. Each cell corresponds to
a fitted model. Now, we will calculate some forecasts using our
model.
forecast_1 <- fit %>%
fabletools::forecast(h = 36)
forecast_1
OK, looking good so far.
forecast_1 %>%
autoplot(animal_complaints_tsibble)

Let’s make our model look pretty and have less clutter
forecast_1 %>%
filter(.model == "arima") %>%
autoplot(animal_complaints_tsibble, level = 95) +
scale_x_yearmonth(date_breaks = "6 months", date_labels = "%b %y") +
labs(title = "Townsville Complaint Calls with Prediction",
x = "Time",
y = "Number of Calls") +
theme_economist() +
theme(axis.text.x = element_text(angle = 45, vjust = 1, family = "mono", face = "bold", size = 7),
#axis.ticks.x =
axis.title.y = element_text(vjust = 3.2),
title = element_text(family = "mono", face = "bold"),
plot.title = element_text(hjust = 0.4),
legend.title = element_blank(),
legend.position = "none") +
annotate("rect", xmin = as.Date("2014-06-01"), xmax = as.Date("2014-08-01"), ymin = -Inf, ymax = Inf, fill = "gray70", alpha = 0.3) +
annotate("rect", xmin = as.Date("2015-06-01"), xmax = as.Date("2015-08-01"), ymin = -Inf, ymax = Inf, fill = "gray70", alpha = 0.3) +
annotate("rect", xmin = as.Date("2016-06-01"), xmax = as.Date("2016-08-01"), ymin = -Inf, ymax = Inf, fill = "gray70", alpha = 0.3) +
annotate("rect", xmin = as.Date("2017-06-01"), xmax = as.Date("2017-08-01"), ymin = -Inf, ymax = Inf, fill = "gray70", alpha = 0.3) +
annotate("rect", xmin = as.Date("2018-06-01"), xmax = as.Date("2018-08-01"), ymin = -Inf, ymax = Inf, fill = "gray70", alpha = 0.3) +
annotate("rect", xmin = as.Date("2019-06-01"), xmax = as.Date("2019-08-01"), ymin = -Inf, ymax = Inf, fill = "gray70", alpha = 0.3) +
annotate("rect", xmin = as.Date("2020-06-01"), xmax = as.Date("2020-08-01"), ymin = -Inf, ymax = Inf, fill = "gray70", alpha = 0.3) +
annotate("rect", xmin = as.Date("2021-06-01"), xmax = as.Date("2021-08-01"), ymin = -Inf, ymax = Inf, fill = "gray70", alpha = 0.3) +
annotate("rect", xmin = as.Date("2022-06-01"), xmax = as.Date("2022-08-01"), ymin = -Inf, ymax = Inf, fill = "gray70", alpha = 0.3) +
annotate("rect", xmin = as.Date("2023-06-01"), xmax = as.Date("2023-08-01"), ymin = -Inf, ymax = Inf, fill = "gray70", alpha = 0.3)

NA
So I was also tasked with creating a model, to predict how things
might look for the next few years. I focused specifically on the
Townsville data, as this was most suitable for forecasting. I used
something called the “ARIMA” model, the inner workings of which are
quite complicated, but basically it predicts the future based on the
past, and is quite good when it comes to seasonal data like I have here.
The blue line is the prediction, and the light blue area you see
highlighted around it is the confidence interval. Think of this like a
margin of error, and it basically means that 95% of the time, our model
will predict results in this area.
This model suggests that roughly the same pattern will continue as
before, with fairly steady volume of calls and high peaks in Winter. But
bear in mind this model is quite limited and shouldn’t be taken as fact;
for example, it doesn’t take into account natural disasters and other
events which could cause an increase in complaint calls.
Documentation note
Fix or discuss the error of NT and NSW swapping for 2016-2018
LS0tCnRpdGxlOiAiQW5hbHlzaXMiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCkJVU0lORVNTIFFVRVNUSU9OUzoKTm90ZTogaWdub3JlIHRoZSBmYWN0IHRoZXJlIGlzIG5vIHF1ZXN0aW9uIDEsIHRoaXMgaXMgZHVlIHRvIGEgZm9ybWF0dGluZyBlcnJvcgoyLiAKYSkgSXMgdGhlcmUgYXJlIGEgdHJlbmQgaW4gaW5qdXJpZXMgQnkgUmVnaW9uLCBhbmQgaXMgdGhlcmUgZGlmZmVyZW50IHBlYWtzIG9mIHRpbWVzIG9mIHllYXIgcGVyIHJlZ2lvbj8KYikgQW5hbHlzaXMgb24gdGhlIHR5cGVzIG9mIGFuaW1hbHMgdGhhdCBhcmUgaW5qdXJlZCwgdGhpcyBhbHNvIGJ5IFJlZ2lvbiDigJMgaXMgdGhlcmUgYSBzcGVjaWVzIHRoYXQgaXMgbW9yZSBsaWFibGUgdG8gaW5qdXJ5IGluIGNlcnRhaW4gcmVnaW9ucz8gLSAoY2F0L2RvZyBieSByZWdpb24pCmMpIFdoYXQgaXMgdGhlIG91dGNvbWU/IERvZXMgdGhpcyBkaWZmZXIgYnkgcmVnaW9uPwoKMy4KYSkgVG90YWwgY2FsbCB2b2x1bWUgZm9yIGNvbXBsYWludCBjYWxsczogSG93IGhhcyB0aGlzIHRyZW5kZWQgb3ZlciB0aW1lPwpiKSBJcyB0aGVyZSBhIHBhcnRpY3VsYXIgYW5pbWFsIGJlaW5nIGNhbGxlZCBhYm91dCB0aGUgbW9zdD8KYykgRG8gcGFydGljdWxhciBzdWJ1cmJzIGhhdmUgZGlmZmVyZW50IHR5cGUgb2YgY29tcGxhaW50IGNhbGxzPyBEbyB0aGV5IGNhbGwgYWJvdXQgZGlmZmVyZW50IGFuaW1hbHM/ICgoTUFLRSBBIExFQUZMRVQgTUFQIEZPUiBUSElTISkpCgo0LgpCdXNpbmVzcyBJbnRlbGxpZ2VuY2Ug4oCTIHVzaW5nIHRoZSBpbnNpZ2h0cyB5b3UgaGF2ZSBmb3VuZCwgY2FuIHlvdSBwcmVkaWN0IGhvdyB0aGlzIG1pZ2h0IGxvb2sgZm9yIHRoZSB1cGNvbWluZyB5ZWFyPwoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHRzaWJibGUpCmxpYnJhcnkoZm9yZWNhc3QpCnNvdXJjZSgiY2xlYW5pbmdfc2NyaXB0LlIiKQpgYGAKCk5vdGU7IHN1bW1lciBpbiBBdXN0cmFsaWEgc2Vhc29uczoKU3VtbWVyOiBEZWNlbWJlciAtIEZlYnJ1YXJ5CkF1dHVtbjogTWFyY2ggLSBNYXkKV2ludGVyOiBKdW5lIC0gQXVndXN0ClNwcmluZzogU2VwdGVtYmVyIC0gTm92ZW1iZXIKCmFsc286IFRoZSAnd2V0IHNlYXNvbicgaW4gQXVzdHJhbGlhJ3MgTm9ydGg6IE5vdmVtYmVyIC0gQXByaWwKCmh0dHBzOi8vd3d3Lm1kcGkuY29tLzIwNzYtMjYxNS84LzcvMTAwICAgd2lsbCB1c2VmdWwgcmVhZGluZyBmb3IgbGF0ZXIsIHRhbGsgYWJvdXQgdGhlIG5lZWQgdG8gcmVkdWNlIGV1dGhhbmFzaWEgb3Igc2ltaWxhciBhbmQgdGhlIGVmZmVjdCB0aGlzIGhhcyBvbiBwZW9wbGUKCkludHJvOgpJbnRyb2R1Y2UgdGhlIHBvaW50IG9mIHRoZSB0YWxrLCB0YWxrIGFib3V0IEF1c3RyYWxpYW4gUlNQQ0EsIHRhbGsgYWJvdXQgaG93IHRoZSBkYXRhIHdhcyBnYXRoZXJlZCAodXNpbmcgdGhlIGluZm9ybWF0aW9uIGZyb20gdGhlIHdlYnNpdGVzKSwgdGhlIFBVUlBPU0Ugb2YgdGhpcyBpbnZlc3RpZ2F0aW9uICh3aGljaCBpcyB0byBoZWxwIHRoZSBSU1BDQSBrbm93IHdoaWNoIGFyZWFzL2FuaW1hbHMgdG8gZm9jdXMgdGhlaXIgZWZmb3J0cyBvbiksIGFzIEknbSBpbnRyb2R1Y2luZyB0aGUgZGF0YXNldHMgSSBjYW4gaW50cm9kdWNlIHRoZSB0d28gZGlmZmVyZW50IGNpdGllcy4gRmlyc3QsIHdlIGNhbiB0YWxrIGEgc2hvcnQgYml0IGFib3V0IEF1c3RyYWxpYSBhcyBhIHdob2xlLCBpdCdzIGNsaW1hdGUsIHRoZSBraW5kIG9mIGFuaW1hbHMgZXRjLiBUaGUgcG9pbnQgaGVyZSBpcyB0byByZWFsbHkgc2V0IHRoZSBzY2VuZSBiZWZvcmUgZGl2aW5nIHRvbyBkZWVwIGludG8gZmFjdHMgYW5kIGZpZ3VyZXMsIGFzIGVzcGVjaWFsbHkgYSBub24tdGVjaG5pY2FsIGF1ZGllbmNlIHRoaXMgd2lsbCBoZWxwIGtlZXAgdGhlbSBlbmdhZ2VkIGFuZCBtYWtlIGEgbW9yZSBob2xpc3RpYyBwcmVzZW50YXRpb24uIEluIG15IG9waW5pb24sIGl0J3MgYWx3YXlzIGdvb2QgdG8gem9vbSBvdXQgYW5kIHNlZSB0aGUgYmlnIHBpY3R1cmUsIHJhdGhlciB0aGFuIGdldHRpbmcgbG9zdCBpbiB0aGUgbXlvcGlhIG9mIHNvbWUgY3N2IGZpbGVzLgoKVG93bnN2aWxsZSBJbnRybzoKVG93bnN2aWxsZSBpcyBhIGNpdHkgb24gdGhlIG5vcnRoLWVhc3Rlcm4gY29hc3Qgb2YgUXVlZW5zbGFuZCwgQXVzdHJhbGlhLiBXaXRoIGEgcG9wdWxhdGlvbiBvZiAxODAsODIwIGFzIG9mIEp1bmUgMjAxOCwgaXQgaXMgdGhlIGxhcmdlc3Qgc2V0dGxlbWVudCBpbiBOb3J0aCBRdWVlbnNsYW5kOyBpdCBpcyB1bm9mZmljaWFsbHkgY29uc2lkZXJlZCBpdHMgY2FwaXRhbC4gW25vdGU6IHB1dCBhIG1hcCBvZiBBdXN0cmFsaWEgd2l0aCBRdWVlbnNsYW5kIGFuZCBUb3duc3ZpbGxlIGhpZ2hsaWdodGVkIGhlcmUuIFRhbGsgYSBsaXR0bGUgYml0IGFib3V0IHRoZSBwb3B1bGF0aW9uIGRlbnNpdHksIHVyYmFuaXNhdGlvbiwgY2xpbWF0ZSwgdHlwZXMgb2YgYW5pbWFscyB0aGF0IGFyZSBjb21tb24gaGVyZSBldGMuIFNob3cgc29tZSBwaG90b3Mgb2YgdGhlIGFyZWEgdG9vXQoKQnJpc2JhbmUgSW50cm86CkV4YWN0IHNhbWUgYXMgYWJvdmUKCiMjIyAzLgphKSBUb3RhbCBjYWxsIHZvbHVtZSBmb3IgY29tcGxhaW50IGNhbGxzOiBIb3cgaGFzIHRoaXMgdHJlbmRlZCBvdmVyIHRpbWU/CgpGaXJzdCwgbGV0J3MgbG9vayBhdCB0aGUgVG93bnN2aWxsZSBhbmltYWwgY29tcGxhaW50cy4KYGBge3J9CmFuaW1hbF9jb21wbGFpbnRzICU+JSAKICBncm91cF9ieShkYXRlX3JlY2VpdmVkKSAlPiUgCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gZGF0ZV9yZWNlaXZlZCwgeSA9IGNvdW50KSkgKwogIGdlb21fbGluZSgpICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiNiBtb250aHMiLCBkYXRlX2xhYmVscyA9ICIlYi0leSIpCmBgYApUaGlzIHNob3dzIHNvbWUgc2Vhc29uYWxpdHkgYW5kIGFsc28gYW4gaW5jcmVhc2UgdGhlbiBhIGRlY2xpbmUuIEVhY2ggc3VtbWVyIChpbiBEZWNlbWJlcikgdGhlIGNhbGxzIGFyZSBtdWNoIGxvd2VyLCByaXNpbmcgYWdhaW4gZWFjaCBXaW50ZXIuIFVzaW5nIGdlb21fc21vb3RoLCB3ZSBnZXQ6CgpgYGB7cn0KYW5pbWFsX2NvbXBsYWludHMgJT4lIAogIGdyb3VwX2J5KGRhdGVfcmVjZWl2ZWQpICU+JSAKICBzdW1tYXJpc2UoY291bnQgPSBuKCkpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBkYXRlX3JlY2VpdmVkLCB5ID0gY291bnQpKSArCiAgZ2VvbV9zbW9vdGgoKSArCiAgZ2VvbV9wb2ludCgpICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSB5ZWFyIiwgZGF0ZV9sYWJlbHMgPSAiJXkiKQpgYGAKClRoaXMgc2hvd3MgYSBiaXQgbW9yZSBjbGVhcmx5IHRoZSBnZW5lcmFsIHRyZW5kIG9mIGNhbGwgdm9sdW1lLiBGcm9tIDIwMTQgaXQgc3RlYWRpbHkgcmlzZXMsIHBlYWtpbmcgaW4gMjAxNy4gQWZ0ZXJ3YXJkcywgaXQgc3RlYWRpbHkgZGVjbGluZXMgdG8gb25seSBzbGlnaHRseSBoaWdoZXIgdGhhbiB3aGVyZSBpdCBzdGFydGVkLiBJdCB3b3VsZCBiZSB2ZXJ5IGRpZmZpY3VsdCB0byBzYXkgd2hldGhlciB0aGlzIHRyZW5kIHdpbGwgY29udGludWUgZG93bndhcmQsIGdvIHVwd2FyZCBvciBzdGF5IHJlbGF0aXZlbHkgZmxhdC4KCgoKCgoKCk5vdGU7IGlmIHdlIGhhdmUgdGltZSBvciBpZiBpdCdzIGhlbHBmdWwsIHdlIHdpbGwgZml4IHRoaXMgZ3JhcGggc28gdGhhdCBxdWFydGVycyBhcmUgcHJvcGVybHkgZGlzcGxheWVkLgpgYGB7cn0KYnJpc2JhbmVfY29tcGxhaW50cyAlPiUgCiAgZ3JvdXBfYnkoZGF0ZSkgJT4lIAogIHN1bW1hcmlzZShjb3VudCA9IG4oKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IGRhdGUsIHkgPSBjb3VudCkpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fbGluZSgpICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMyBtb250aHMiLCBkYXRlX2xhYmVscyA9ICIleSIpCmBgYAoKQWdhaW4sIHdlIHNlZSB0aGUgc2Vhc29uYWxpdHkgb2Ygd2ludGVyIGhhdmluZyBtb3JlIGNhbGxzLiBUaGUgZmFjdCB0aGlzIGlzIGluIGJvdGggQnJpc2JhbmUgYW5kIFRvd25zdmlsbGUgc3VnZ2VzdHMgYSBmYWlybHkgZ2VuZXJhbCB0cmVuZC4KCmBgYHtyfQpicmlzYmFuZV9jb21wbGFpbnRzICU+JSAKICBncm91cF9ieShkYXRlKSAlPiUgCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gZGF0ZSwgeSA9IGNvdW50KSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgoKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gIjEgeWVhciIsIGRhdGVfbGFiZWxzID0gIjIwJXkiKQpgYGAKCk90aGVyIHRoYW4gZGVjbGluaW5nIGEgbGl0dGxlIG92ZXIgMjAxNiwgdGhlIG51bWJlciBvZiBjYWxscyBzZWVzIGEgc2xvdyBidXQgc3RlYWR5IGluY3JlYXNlIHRvd2FyZHMgMjAyMCwgYmVpbmcgdGhvdXNhbmRzIG1vcmUgdGhhbiBpdCB3YXMgaW4gMjAxNiBhbmQgMjAxNy4gU28sIHRoZSBnZW5lcmFsIHRyZW5kIGlzIHRoYXQgdGhlIFJTUENBIGFyZSBnZXR0aW5nIG1vcmUgY29tcGxhaW50cyBhcyB0aW1lIGdvZXMgb24uIE5vdywgdGhpcyBkb2VzIG5vdCBuZWNlc3NhcmlseSBtZWFuIHRoZSBsaW5lIHdpbGwgY29udGludWUgdG8gZ28gdXAuIFdlIGFyZSBhbHNvIG1pc3NpbmcgUTMgZnJvbSAyMDE2IHNvIHRoaXMgc2tld3MgdGhlIGN1cnZlIGEgbGl0dGxlCgoKCiMjIyAzLmIpIElzIHRoZXJlIGEgcGFydGljdWxhciBhbmltYWwgYmVpbmcgY2FsbGVkIGFib3V0IHRoZSBtb3N0PwoKYGBge3J9CmFuaW1hbF9jb21wbGFpbnRzICU+JSAKICBncm91cF9ieShhbmltYWxfdHlwZSkgJT4lIAogIGdncGxvdChhZXMoeCA9IGFuaW1hbF90eXBlKSkgKwogIGdlb21fYmFyKCkKYGBgCgpUaGUgbnVtYmVyIG9mIGNhbGxzIGFib3V0IGRvZ3MgZHdhcmYgdGhvc2UgYWJvdXQgY2F0cyBodWdlbHkuIExldCdzIGxvb2sgYXQgc3BlY2lmaWMgbnVtYmVyczoKYGBge3J9CmFuaW1hbF9jb21wbGFpbnRzICU+JSAKICBncm91cF9ieShhbmltYWxfdHlwZSkgJT4lCiAgY291bnQoKSAlPiUgCiAgc3VtbWFyaXNlKG4sIDQwOTQgLyAzODMxOSkKYGBgCgpTbyBjYXRzIGFjY291bnQgZm9yIG9ubHkgMTAlIG9mIHRoZSBjYWxscyBkb2dzIGRvIGZvciBUb3duc3ZpbGxlISBMZXQncyBsb29rIGF0IEJyaXNiYW5lOgoKYGBge3J9CmJyaXNiYW5lX2NvbXBsYWludHMgJT4lIAogIGdyb3VwX2J5KHR5cGVfb2ZfYW5pbWFsKSAlPiUKICBjb3VudCgpCgpicmlzYmFuZV9jb21wbGFpbnRzICU+JSAKICBncm91cF9ieSh0eXBlX29mX2FuaW1hbCkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gdHlwZV9vZl9hbmltYWwpKSArCiAgZ2VvbV9iYXIoKQpgYGAKCldlIGhhdmUgYSBsb3QgbW9yZSBhbmltYWwgdHlwZXMgaGVyZSB0aGF0IHdlIGRvbid0IGluIHRoZSBwcmV2aW91cyBkYXRhLiBXZSBhbHNvIGhhdmUgbWFueSBjYWxscyBhYm91dCBBdHRhY2tzIHdpdGggbm8gYW5pbWFsIHNwZWNpZmllZCwgbWFueSBvZiB3aGljaCBpdCBpcyB2ZXJ5IGxpa2VseSB0aGV5IHdlcmUgaW52b2x2aW5nIGRvZ3MuIEhvd2V2ZXIsIHdlIGNhbid0IHNheSB0aGlzIGZvciBzdXJlLgoKU28gdGhhdCBtYWtlcyAKYGBge3J9CjQ3NDUgLyAxMzMzNCAgIyBjYXRzIGFyZSAzNSUgb2YgdGhlIGNhbGxzIGNvbXBhcmVkIHRvIGRvZ3MKCgoKIyBhbGwgb3RoZXIgYW5pbWFscyBkaXZpZGVkIGJ5IGRvZ3MsIGxlYXZpbmcgb3V0IHVuc3BlY2lmaWVkICh3aGljaCB3ZSBiZWxpZXZlIHBvdGVudGlhbGx5IGNvbnRhaW4gYSBoaWdoIHByb3BvcnRpb24gb2YgZG9ncykKOTQ1NyAvIDEzMzQ5CmBgYAoKTW9zdCBvZiB0aGUgb3RoZXIgYW5pbWFscyBoYXZlIHZlcnkgc21hbGwgY291bnRzLCBpbnRlcmVzdGluZ2x5IGZveGVzIHNlZW0gdG8gbWFrZSB1cCBhIGRlY2VudCBwcm9wb3J0aW9uIG9mIHRoZSBjYWxscyByZWdhcmRpbmcgd2lsZCBhbmltYWxzLgoKVG8gYW5zd2VyIHRoZSBxdWVzdGlvbiBob3dldmVyLCBpdCdzIG1haW5seSBkb2dzIGFuZCBjYXRzLCBhbmQgZXNwZWNpYWxseSBkb2dzLiBEb2dzIGFyZSBiZWluZyBjYWxsZWQgYWJvdXQgbW9yZSB0aGFuIGFueSBvZiB0aGUgb3RoZXIgYW5pbWFscyBjb21iaW5lZCAoaWYgd2UgbGVhdmUgVW5zcGVjaWZpZWQgdG8gdGhlIHNpZGUpCgooQXR0YWNrIHJlZmVycyB0byB0aGUgaW5pdGlhbCBkZXNjcmlwdGlvbiBvZiB0aGUgY29tcGxhaW50KQoKCiMjIyAzLiBjKSBEbyBwYXJ0aWN1bGFyIHN1YnVyYnMgaGF2ZSBkaWZmZXJlbnQgdHlwZSBvZiBjb21wbGFpbnQgY2FsbHM/IERvIHRoZXkgY2FsbCBhYm91dCBkaWZmZXJlbnQgYW5pbWFscz8KCk9LLCBzbyB0aGlzIG9uZSBpcyBkaWZmaWN1bHQgc2ltcGx5IGZvciB0aGUgZmFjdCB0aGVyZSBpcyBhIGh1Z2UgYW1vdW50IG9mIHN1YnVyYnMuCmBgYHtyfQpicmlzYmFuZV9jb21wbGFpbnRzICU+JSAKICBncm91cF9ieShzdWJ1cmIpICU+JSAKICBjb3VudCgpCgojIFRoZXJlIGlzIDE5MiBzdWJ1cmJzISBDZXJ0YWlubHkgdXNpbmcgYSBmaWxsIG9uIGEgZ3JhcGggaXMgbm90IGdvbm5hIHdvcmssIG5laXRoZXIgaXMgcHV0dGluZyB0aGVtIG9uIHRoZSB4LWF4aXMgb24gYSBiYXIgZ3JhcGguCgphbmltYWxfY29tcGxhaW50cyAlPiUgCiAgZ3JvdXBfYnkoc3VidXJiKSAlPiUgCiAgY291bnQoKQojIDg1IHN1YnVyYnMgZm9yIFRvd25zdmlsbGUKCmFuaW1hbF9jb21wbGFpbnRzICU+JSAKICBncm91cF9ieShlbGVjdG9yYWxfZGl2aXNpb24pICU+JSAKICBjb3VudCgpCiMgYWxzbyAxMSBlbGVjdG9yYWwgZGl2aXNpb25zLiBDb3VsZCB3ZSBsb29rIGF0IHN1YnVyYnMgb25lIGVsZWN0b3JhbCBkaXZpc2lvbiBhdCBhIHRpbWU/IFBvc3NpYmx5CmBgYAoKSWRlYTogV2hhdCBhYm91dCB1c2luZyBsZWFmbGV0IHRvIHZpc3VhbGlzZSB0eXBlcyBvZiBjb21wbGFpbnQgY2FsbHMgb24gYSBtYXA/CgpUaGlzIGlzIG1vcmUgZmVhc2libGUgd2l0aCB0aGUgVG93bnN2aWxsZSBkYXRhc2V0cywgYXMgaXQgaGFzIGxlc3Mgc3VidXJicyBhbmQgb25seSA2IHR5cGVzIG9mIGNvbXBsYWludHMuIEl0IG1heSBiZSBuZWNlc3NhcnkgdG8gdHJ5IGFuZCB3cmFuZ2xlIHRoZSBCcmlzYmFuZSBkYXRhIGEgbGl0dGxlIGZ1cnRoZXIgdG8gbmFycm93IGRvd24gY2F0ZWdvcmllcyAoZm9yIGJvdGggdHlwZV9vZl9hbmltYWwgYW5kIGNvbXBsYWludF90eXBlKQoKRk9SIFRPV05TVklMTEUgV0UgSEFWRToKODUgZGlmZmVyZW50IHN1YnVyYnMKNiBjb21wbGFpbnQgdHlwZXMKMiBhbmltYWwgdHlwZXMKCldlIHdhbnQgdG8gYnJlYWsgaXQgZG93biBieSBzdWJ1cmIgYW5kIGNvbXBsYWludCB0eXBlLCBhbmQgdGhlbiBieSBzdWJ1cmIgYW5kIGFuaW1hbCB0eXBlCmBgYHtyfQphbmltYWxfY29tcGxhaW50cyAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gc3VidXJiLCBmaWxsID0gYW5pbWFsX3R5cGUpKSArCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIpICsKICBjb29yZF9mbGlwKCkgKwogIHNjYWxlX3hfZGlzY3JldGUoZ3VpZGUgPSBndWlkZV9heGlzKG4uZG9kZ2UgPSA1KSkKYGBgCgpgYGB7cn0KYW5pbWFsX2NvbXBsYWludHMgJT4lIAogIGdncGxvdChhZXMoeCA9IHN1YnVyYiwgZmlsbCA9Y29tcGxhaW50X3R5cGUpKSArCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIpIAogICNjb29yZF9mbGlwKCkgKwogICNzY2FsZV94X2Rpc2NyZXRlKGd1aWRlID0gZ3VpZGVfYXhpcyhuLmRvZGdlID0gNSkpCmBgYAoKVGhlIGNoYWxsZW5nZSBhZ2FpbiwgaXMgaGF2aW5nIHRvbyBtYW55IHN1YnVyYnMgdGhhdCB3ZSBjYW4ndCBnZXQgYW55IHVzZWZ1bCBpbmZvcm1hdGlvbiBvdXQgb2YgdGhlIGdyYXBocwoKYGBge3J9CmFuaW1hbF9jb21wbGFpbnRzICU+JSAKICBncm91cF9ieShzdWJ1cmIpICU+JSAKICBjb3VudChzb3J0ID0gVFJVRSkKCiMgbGV0J3MgZHJvcCBhbnkgc3VidXJicyB3aXRoIGxlc3MgdGhhbiAyMDAgY2FzZXMKCmFuaW1hbF9jb21wbGFpbnRzICU+JSAKICBncm91cF9ieShzdWJ1cmIpICU+JSAKICBzdW1tYXJpc2UoY291bnQgPSBuKCksIGFuaW1hbF90eXBlKSAlPiUgCiAgZmlsdGVyKGNvdW50ID49IDUwMCkgJT4lIAogIGdncGxvdChhZXMoeCA9IHN1YnVyYiwgeSA9IGNvdW50LCBmaWxsID0gYW5pbWFsX3R5cGUpKSArCiAgZ2VvbV9jb2woKSArCiAgY29vcmRfZmxpcCgpCmBgYAoKVGhlIGhpZ2hlc3QgY291bnQgYnkgcXVpdGUgYSBsYXJnZSBtYXJnaW4gaXMgdW5hbGxvY2F0ZWQgdG8gYSBzcGVjaWZpYyBzdWJ1cmIuCgpgYGB7cn0KYW5pbWFsX2NvbXBsYWludHMgJT4lIAogIGdyb3VwX2J5KHN1YnVyYikgJT4lIAogIHN1bW1hcmlzZShjb3VudCA9IG4oKSwgYW5pbWFsX3R5cGUpICU+JSAKICBmaWx0ZXIoY291bnQgPj0gNTAwKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gc3VidXJiLCB5ID0gY291bnQsIGZpbGwgPSBhbmltYWxfdHlwZSkpICsKICBnZW9tX2NvbChwb3NpdGlvbiA9ICJmaWxsIikgKwogIGNvb3JkX2ZsaXAoKSAKYGBgCkF0IGEgZ2xhbmNlLCB0aGVyZSdzIG5vIGJpZyBkaWZmZXJlbmNlIG9uIGFuaW1hbCB0eXBlcy4gQWxsIHRoZSBzdWJ1cmJzIGhhdmUgYSBsYXJnZSBtYWpvcml0eSBvZiBkb2dzLiBDb3VsZCB3ZSBkbyBhIGh5cG90aGVzaXMgdGVzdCB0byBzZWUgaWYgdGhlcmUgaXMgYSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IGRpZmZlcmVuY2U/CgpgYGB7cn0KYW5pbWFsX2NvbXBsYWludHMgJT4lIAogIGdyb3VwX2J5KHN1YnVyYikgJT4lIAogIHN1bW1hcmlzZShjb3VudCA9IG4oKSwgYW5pbWFsX3R5cGUpICU+JSAKICBmaWx0ZXIoY291bnQgPCA1MDAgJiBjb3VudCA+IDEwMCkgJT4lIAogIGdncGxvdChhZXMoeCA9IHN1YnVyYiwgeSA9IGNvdW50LCBmaWxsID0gYW5pbWFsX3R5cGUpKSArCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZmlsbCIpICsKICBjb29yZF9mbGlwKCkgCmBgYApMb29raW5nIGF0IHRoZSBsb3dlciBlbmQgb2YgdGhlIHBvcHVsYXRpb24sIHdlIHNlZSBhbiBvdXRsaWVyLiBUb3duc3ZpbGxlIENpdHkgaGFzIHdheSBtb3JlIGNhdHMgdGhhbiBhbnkgb2YgdGhlIG90aGVyIHN1YnVyYnMuIEluIGZhY3QsIGl0J3MgYWxtb3N0IDUwLzUwIQoKTm93IHN0aWxsIGxvb2tpbmcgYXQgdGhlIFRvd25zdmlsbGUgZGF0YXNldCwgd2UnbGwgYnJlYWsgaXQgZG93biBieSBjb21wbGFpbnQgdHlwZToKYGBge3J9CmFuaW1hbF9jb21wbGFpbnRzICU+JSAKICBncm91cF9ieShzdWJ1cmIpICU+JSAKICBzdW1tYXJpc2UoY291bnQgPSBuKCksIGNvbXBsYWludF90eXBlKSAlPiUgCiAgZmlsdGVyKGNvdW50ID49IDUwMCAmIGNvdW50IDw9IDQwMDApICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBzdWJ1cmIsIHkgPSBjb3VudCwgZmlsbCA9IGNvbXBsYWludF90eXBlKSkgKwogIGdlb21fY29sKHBvc2l0aW9uID0gImZpbGwiKSArCiAgY29vcmRfZmxpcCgpIApgYGAKCk5vdyBmb3IgdGhlIGxvd2VyIGVuZCBvZiB0aGUgY291bnQ6CmBgYHtyfQphbmltYWxfY29tcGxhaW50cyAlPiUgCiAgZ3JvdXBfYnkoc3VidXJiKSAlPiUgCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpLCBjb21wbGFpbnRfdHlwZSkgJT4lIAogIGZpbHRlcihjb3VudCA8IDUwMCAmIGNvdW50ID4gNTApICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBzdWJ1cmIsIHkgPSBjb3VudCwgZmlsbCA9IGNvbXBsYWludF90eXBlKSkgKwogIGdlb21fY29sKHBvc2l0aW9uID0gImZpbGwiKSArCiAgY29vcmRfZmxpcCgpIApgYGAKCkknbSBub3Qgc3VyZSBtdWNoIGNhbiBiZSBnbGVhbWVkIHdpdGggc28gbWFueSBjb21wbGFpbnRfdHlwZXMuIExldCdzIHRyeSBmb2N1c2luZyBtb3JlIHNwZWNpZmljYWxseS4KCk9uZSB0aGluZyB0byBub3RlIGhlcmUsIGlzIHRoZSB2YXN0IHZhcmlhdGlvbiBpbiB0b2xlcmFuY2UgZm9yIG5vaXNlLiBNb3N0IGNhdGVnb3JpZXMgYXJlIGNvbnNpc3RlbnQgZXhjZXB0IHRoaXMgb25lLiBDbHVkZW4gZm9yIGV4YW1wbGUgaGFzIGEgc21hbGwgcGVyY2VudGFnZSBvZiBub2lzZSBjb21wbGFpbnRzLHdoaWxlIEJvaGxlIFBsYWlucyBoYXMgYSBodWdlIHBlcmNlbnRhZ2UuIFRoaXMgcmVxdWlyZXMgbW9yZSBpbnZlc3RpZ2F0aW9uIHRvIGZpZ3VyZSBvdXQgdGhlIHJvb3QgY2F1c2Ugb2YgdGhpczogCgpgYGB7cn0KYW5pbWFsX2NvbXBsYWludHMgJT4lIAogIGdyb3VwX2J5KHN1YnVyYikgJT4lIAogIHN1bW1hcmlzZShjb3VudCA9IG4oKSwgY29tcGxhaW50X3R5cGUpICU+JSAKICBmaWx0ZXIoY291bnQgPj0gNTAwKSAlPiUgCiAgZmlsdGVyKGNvbXBsYWludF90eXBlID09ICJOb2lzZSIgfCAoY29tcGxhaW50X3R5cGUgPT0gIkF0dGFjayIpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gc3VidXJiLCB5ID0gY291bnQsIGZpbGwgPSBjb21wbGFpbnRfdHlwZSkpICsKICBnZW9tX2NvbChwb3NpdGlvbiA9ICJmaWxsIikgKwogIGNvb3JkX2ZsaXAoKSAKCmFuaW1hbF9jb21wbGFpbnRzICU+JSAKICBncm91cF9ieShzdWJ1cmIpICU+JSAKICBzdW1tYXJpc2UoY291bnQgPSBuKCksIGNvbXBsYWludF90eXBlKSAlPiUgCiAgZmlsdGVyKGNvdW50ID49IDUwMCkgJT4lIAogIGZpbHRlcihjb21wbGFpbnRfdHlwZSA9PSAiTm9pc2UiIHwgKGNvbXBsYWludF90eXBlID09ICJBZ2dyZXNzaXZlIEFuaW1hbCIpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gc3VidXJiLCB5ID0gY291bnQsIGZpbGwgPSBjb21wbGFpbnRfdHlwZSkpICsKICBnZW9tX2NvbChwb3NpdGlvbiA9ICJmaWxsIikgKwogIGNvb3JkX2ZsaXAoKSAKCmFuaW1hbF9jb21wbGFpbnRzICU+JSAKICBncm91cF9ieShzdWJ1cmIpICU+JSAKICBzdW1tYXJpc2UoY291bnQgPSBuKCksIGNvbXBsYWludF90eXBlKSAlPiUgCiAgZmlsdGVyKGNvdW50ID49IDUwMCkgJT4lIAogIGZpbHRlcihjb21wbGFpbnRfdHlwZSA9PSAiV2FuZGVyaW5nIiB8IChjb21wbGFpbnRfdHlwZSA9PSAiQWdncmVzc2l2ZSBBbmltYWwiKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IHN1YnVyYiwgeSA9IGNvdW50LCBmaWxsID0gY29tcGxhaW50X3R5cGUpKSArCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZmlsbCIpICsKICBjb29yZF9mbGlwKCkgCgphbmltYWxfY29tcGxhaW50cyAlPiUgCiAgZ3JvdXBfYnkoc3VidXJiKSAlPiUgCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpLCBjb21wbGFpbnRfdHlwZSkgJT4lIAogIGZpbHRlcihjb3VudCA+PSA1MDApICU+JSAKICBmaWx0ZXIoY29tcGxhaW50X3R5cGUgPT0gIkVuY2xvc3VyZSIgfCAoY29tcGxhaW50X3R5cGUgPT0gIk5vaXNlIikpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBzdWJ1cmIsIHkgPSBjb3VudCwgZmlsbCA9IGNvbXBsYWludF90eXBlKSkgKwogIGdlb21fY29sKHBvc2l0aW9uID0gImZpbGwiKSArCiAgY29vcmRfZmxpcCgpIApgYGAKCkZvciB0aGUgbGVzcyB0aGFuIDUwMCBncmVhdGVyIHRoYW4gNTAgZ3JvdXBzOgpgYGB7cn0KYW5pbWFsX2NvbXBsYWludHMgJT4lIAogIGdyb3VwX2J5KHN1YnVyYikgJT4lIAogIHN1bW1hcmlzZShjb3VudCA9IG4oKSwgY29tcGxhaW50X3R5cGUpICU+JSAKICBmaWx0ZXIoY291bnQgPCA1MDAgJiBjb3VudCA+IDEwMCkgJT4lIAogIGZpbHRlcihjb21wbGFpbnRfdHlwZSA9PSAiTm9pc2UiIHwgKGNvbXBsYWludF90eXBlID09ICJBdHRhY2siKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IHN1YnVyYiwgeSA9IGNvdW50LCBmaWxsID0gY29tcGxhaW50X3R5cGUpKSArCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZmlsbCIpICsKICBjb29yZF9mbGlwKCkgCgphbmltYWxfY29tcGxhaW50cyAlPiUgCiAgZ3JvdXBfYnkoc3VidXJiKSAlPiUgCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpLCBjb21wbGFpbnRfdHlwZSkgJT4lIAogIGZpbHRlcihjb3VudCA8IDUwMCAmIGNvdW50ID4gMTAwKSAlPiUgIAogIGZpbHRlcihjb21wbGFpbnRfdHlwZSA9PSAiTm9pc2UiIHwgKGNvbXBsYWludF90eXBlID09ICJBZ2dyZXNzaXZlIEFuaW1hbCIpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gc3VidXJiLCB5ID0gY291bnQsIGZpbGwgPSBjb21wbGFpbnRfdHlwZSkpICsKICBnZW9tX2NvbChwb3NpdGlvbiA9ICJmaWxsIikgKwogIGNvb3JkX2ZsaXAoKSAKCmFuaW1hbF9jb21wbGFpbnRzICU+JSAKICBncm91cF9ieShzdWJ1cmIpICU+JSAKICBzdW1tYXJpc2UoY291bnQgPSBuKCksIGNvbXBsYWludF90eXBlKSAlPiUgCiAgZmlsdGVyKGNvdW50IDwgNTAwICYgY291bnQgPiAxMDApICU+JSAKICBmaWx0ZXIoY29tcGxhaW50X3R5cGUgPT0gIldhbmRlcmluZyIgfCAoY29tcGxhaW50X3R5cGUgPT0gIkFnZ3Jlc3NpdmUgQW5pbWFsIikpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBzdWJ1cmIsIHkgPSBjb3VudCwgZmlsbCA9IGNvbXBsYWludF90eXBlKSkgKwogIGdlb21fY29sKHBvc2l0aW9uID0gImZpbGwiKSArCiAgY29vcmRfZmxpcCgpIAoKYW5pbWFsX2NvbXBsYWludHMgJT4lIAogIGdyb3VwX2J5KHN1YnVyYikgJT4lIAogIHN1bW1hcmlzZShjb3VudCA9IG4oKSwgY29tcGxhaW50X3R5cGUpICU+JSAKICBmaWx0ZXIoY291bnQgPCA1MDAgJiBjb3VudCA+IDEwMCkgJT4lIAogICNmaWx0ZXIoY29tcGxhaW50X3R5cGUgPT0gIkVuY2xvc3VyZSIgfCAoY29tcGxhaW50X3R5cGUgPT0gIk5vaXNlIikpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBzdWJ1cmIsIHkgPSBjb3VudCwgZmlsbCA9IGNvbXBsYWludF90eXBlKSkgKwogIGdlb21fY29sKHBvc2l0aW9uID0gImZpbGwiKSArCiAgY29vcmRfZmxpcCgpICsKICBmYWNldF93cmFwKH4gc3VidXJiKQpgYGAKCgpgYGB7cn0KYW5pbWFsX2NvbXBsYWludHMgJT4lIAogIGdyb3VwX2J5KHN1YnVyYikgJT4lIAogIHN1bW1hcmlzZShjb3VudCA9IG4oKSwgY29tcGxhaW50X3R5cGUsIGFuaW1hbF90eXBlKSAlPiUgCiAgZmlsdGVyKGNvdW50IDwgNTAwICYgY291bnQgPiAxMDApICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBjb21wbGFpbnRfdHlwZSwgeSA9IGNvdW50LCBmaWxsID0gY29tcGxhaW50X3R5cGUpKSArCiAgZ2VvbV9jb2woKSArCiAgZmFjZXRfd3JhcCh+IHN1YnVyYikKYGBgCgpGcm9tIHRoaXMgZ3JhcGgsIHdlIGNhbiBzZWUgdGhhdCBIeWRlIFBhcmsgaGFzIGEgZGlzcHJvcG9ydGlvbmF0ZSBhbW91bnQgb2YgcHJpdmF0ZSBpbXBvdW5kcywgd2hpbGUgQm9obGUgcGxhaW5zIGhhcyBtb3JlIG5vaXNlIGNvbXBsYWludHMuCgpQb3RlbnRpYWwgaHlwb3RoZXNpcyB0ZXN0OgoKVGhhdCB0aGUgbGV2ZWwgb2YgcHJpdmF0ZSBpbXBvdW5kcyBpbiBIeWRlIFBhcmsgYmVpbmcgZ3JlYXRlciBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LgoKVGhhdCB0aGUgbGV2ZWwgb2Ygbm9pc2UgaW4gQm9obGUgUGxhaW5zIGJlaW5nIGdyZWF0ZXIgaXMgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudC4KYGBge3J9CmFuaW1hbF9jb21wbGFpbnRzICU+JSAKICBncm91cF9ieShzdWJ1cmIpICU+JSAKICBjb3VudCgpICU+JSAKICBmaWx0ZXIobiA8IDUwMCAmIG4gPiAxMDApCmBgYAoKCgoKCgpMZXQncyBsb29rIGF0IHRoZSBzdWJ1cmJzIHdpdGggbXVjaCBoaWdoZXIgY29tcGxhaW50cyBub3c6CgpgYGB7cn0KYW5pbWFsX2NvbXBsYWludHMgJT4lIAogIGdyb3VwX2J5KHN1YnVyYikgJT4lIAogIHN1bW1hcmlzZShjb3VudCA9IG4oKSwgY29tcGxhaW50X3R5cGUsIGFuaW1hbF90eXBlKSAlPiUgCiAgZmlsdGVyKGNvdW50ID49IDUwMCAmIGNvdW50IDw0MDAwKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gY29tcGxhaW50X3R5cGUsIHkgPSBjb3VudCwgZmlsbCA9IGNvbXBsYWludF90eXBlKSkgKwogIGdlb21fY29sKCkgKwogIGZhY2V0X3dyYXAofiBzdWJ1cmIpCmBgYAoKCgoKCiMjIyAyLiBhKSBBcmUgdGhlcmUgYW55IG1ham9yIGRpZmZlcmVuY2VzIGJldHdlZW4gcmVnaW9ucz8KCmIpIEhvdyBkbyB0aGUgYW5pbWFsIG91dGNvbWVzIGRpZmZlciBvdmVyIHRpbWU/CgpjKSBBcmUgdGhlcmUgYW55IG5vdGljZWFibGUgYW5vbWFsaWVzIGluIHRoZSBkYXRhPwoKCkl0J3MgaW1wb3NzaWJsZSB0byBzYXkgaWYgdGhlcmUncyBkaWZmZXJlbnQgcGVha3Mgb2YgdGltZXMgb2YgeWVyIHBlciByZWdpb24sIGFzIHdlIG9ubHkgaGF2ZSB0aGUgZGF0YSBmb3IgdGhlIHllYXIgYXMgYSB3aG9sZS4gVW5sZXNzIHdlIGxvb2sgYXQgU3VidXJiIHJhdGhlciB0aGFuIHJlZ2lvbiwgYW5kIGJyZWFrIHRoaXMgZG93biBieSB0aW1lLiBIb3dldmVyLCBJIHRoaW5rIGl0J2QgYmUgZ29vZCB0byB1c2UgdGhlIGdlbmVyYWwgQXV0cmFsaWEgKG5hdGlvbndpZGUpIGRhdGEuCgoKUHJvcG9ydGlvbnMgb3ZlcmFsbCBieSByZWdpb24gYW5kIGJ5IG91dGNvbWUuIFdlIGNhbiBzZWUgdGhhdCBpbiBnZW5lcmFsLCByZWdpb25zIGhhdmUgcHJldHR5IHNpbWlsYXIgcHJvcG9ydGlvbnMgYWNyb3NzIGFsbCBvdXRjb21lcy4gVGhpcyB3b24ndCBiZSB0aGUgY2FzZSBmb3IgZXZlcnkgeWVhciB0aG91Z2ggYW5kIHRyZW5kcyBvdmVyIHRpbWUsIHRoYXQncyB0aGUgbW9yZSBpbnRlcmVzdGluZyBzdHVmZi4KYGBge3IsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFLCBldmFsPVRSVUV9CmFuaW1hbF9vdXRjb21lcyAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gcmVnaW9uLCB5ID0gbnVtYmVyX29mX29jY3VyZW5jZXMsIGZpbGwgPSBvdXRjb21lLCBjb2wgPSBvdXRjb21lKSkgKwogIGdlb21fY29sKHBvc2l0aW9uID0gImZpbGwiKQpgYGAKClRoaXMgaXMgdGhlIHNhbWUgdGhpbmcgYXMgYmVmb3JlLCBidXQgZm9yIGFuaW1hbCB0eXBlLiBTYW1lIGFzIGJlZm9yZSwgbm90IG11Y2ggZGlzY2VybmlibGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSByZWdpb25zLgpgYGB7ciwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0UsIGV2YWw9VFJVRX0KYW5pbWFsX291dGNvbWVzICU+JSAKICBnZ3Bsb3QoYWVzKHggPSByZWdpb24sIHkgPSBudW1iZXJfb2Zfb2NjdXJlbmNlcywgZmlsbCA9IGFuaW1hbF90eXBlLCBjb2wgPSBhbmltYWxfdHlwZSkpICsKICBnZW9tX2NvbChwb3NpdGlvbiA9ICJmaWxsIikKYGBgCgoKCgpOZXh0IGlzIGp1c3QgdGhlIHN1bSBvY3VycmVuY2VzLiBXZSBjYW4gc2VlIHRoZSByZWdpb25zIHRoYXQgaGF2ZSB3YXkgbW9yZSBhbmltYWxzIGluanVyZWQvdGFrZW4gaW4gYnkgdGhlIFJTUENBLiBUaGlzIGNvdWxkIGJlIGEgcG9wdWxhdGlvbiB0aGluZywgbWF5YmUgdGhlc2UgcmVnaW9ucyBqdXN0IGhhdmUgbW9yZSB3aWxkbGlmZSBwb3B1bGF0aW9ucyBldGMuLCBvciBldmVuIGEgYmlnZ2VyIFJTUENBIHByZXNlbmNlIGxlYWRpbmcgdG8gbW9yZSBjYXNlcy4KYGBge3IsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFLCBldmFsPVRSVUV9CmFuaW1hbF9vdXRjb21lcyAlPiUgCiAgZ3JvdXBfYnkocmVnaW9uKSAlPiUgCiAgc3VtbWFyaXNlKHN1bV9vZl9vY2N1cmVuY2VzID0gc3VtKG51bWJlcl9vZl9vY2N1cmVuY2VzLCBuYS5ybSA9IFRSVUUpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gcmVnaW9uLCB5ID0gc3VtX29mX29jY3VyZW5jZXMpKSArCiAgZ2VvbV9jb2woY29sID0gImJsdWUiLCBmaWxsID0gImJsdWUiKQpgYGAKCgoKU28sIHRoaXMgaXMgdGhlIGRhdGEgYWNyb3NzIHRpbWUgKGZyb20gMTk5OS0yMDE4KSwgd2l0aCB0aW1lIG9uIHRoZSB4LWF4aXMgYW5kIG51bWJlciBvZiBvY2N1cmVuY2VzIG9uIHRoZSB5LiBGYWNldGVkIGludG8gZ3JhcGhzIGJhc2VkIG9uIG91dGNvbWUsIHdpdGggdGhlIGNvbG91cmVkIGxpbmVzIHJlcHJlc2VudGluZyBkaWZmZXJlbnQgcmVnaW9ucy4KYGBge3IsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFLCBldmFsPVRSVUV9CmFuaW1hbF9vdXRjb21lcyAlPiUgCiAgZHJvcF9uYSgpICU+JSAKICBncm91cF9ieShyZWdpb24sIG91dGNvbWUsIHllYXIpICU+JQogIHN1bW1hcml6ZSh0b3RhbF9pbmp1cmllcyA9IHN1bShudW1iZXJfb2Zfb2NjdXJlbmNlcykpICU+JQogIHVuZ3JvdXAoKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgeSA9IHRvdGFsX2luanVyaWVzLCBjb2xvciA9IHJlZ2lvbikpICsKICBnZW9tX2xpbmUoKSArCiAgZmFjZXRfd3JhcCh+b3V0Y29tZSwgc2NhbGVzID0gImZyZWVfeSIpICsKICBsYWJzKHggPSAiRGF0ZSIsIHkgPSAiTnVtYmVyIG9mIGluanVyaWVzIiwgY29sb3IgPSAiUmVnaW9uIikKCmBgYAoKV2hhdCBjYW4gd2Ugc2F5IGFib3V0IHRoaXM/IFdlbGwsIFFMRCBoYXMgaGFkIHRoZWlyIHRyYW5zZmVycyBnbyB3YXkgdXAgc2luY2UgYWJvdXQgMjAwOSwgYW5kIGluIGdlbmVyYWwgbG9va3MgbGlrZSBhbiBpbmNyZWFzZSBpbiBjYXNlcyBmb3IgdGhlbS4gTlNXIGhhZCBhIGJpZyBzcGlrZSBvZiBDdXJyZW50bHkgSW4gQ2FyZSBhcm91bmQgMjAwNC4gRXV0aGFuaXNhdGlvbiBpbiBnZW5lcmFsIHNlZW1zIHRvIGJlIGZhbGxpbmcgb3V0IG9mIGZhdm91ciAod2hpY2ggaXMgYWN0dWFsbHkgdHJ1ZSwgdGhlIFJTUENBIHRyaWVzIHRvIGRvIGl0IGxlc3MgZm9yIHZhcmlvdXMgcmVhc29ucywgb25lIGFjdHVhbGx5IGJlaW5nIHRoZSBtZW50YWwgaGVhbHRoIG9mIHRoZSBzdGFmZiBhbmQgYW5vdGhlciBiZWluZyBsb3RzIG9mIGV1dGhhbmlzYXRpb25zIGxlYWRzIHRvIGEgbmVnYXRpdmUgcGVyY2VwdGlvbiBvZiBhbmltYWwgc2hlbHRlcnMpCgoKCgpFeGFjdCBzYW1lIGFzIGJlZm9yZSwgYnV0IGZhY2V0ZWQgb24gYW5pbWFsIHR5cGUgcmF0aGVyIHRoYW4gb3V0Y29tZS4KYGBge3IsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFLCBldmFsPVRSVUV9CmFuaW1hbF9vdXRjb21lcyAlPiUgCiAgZHJvcF9uYSgpICU+JSAKICBncm91cF9ieShyZWdpb24sIGFuaW1hbF90eXBlLCB5ZWFyKSAlPiUKICBzdW1tYXJpemUodG90YWxfaW5qdXJpZXMgPSBzdW0obnVtYmVyX29mX29jY3VyZW5jZXMpKSAlPiUKICB1bmdyb3VwKCkgJT4lIAogIGdncGxvdChhZXMoeCA9IHllYXIsIHkgPSB0b3RhbF9pbmp1cmllcywgY29sb3IgPSByZWdpb24pKSArCiAgZ2VvbV9saW5lKCkgKwogIGZhY2V0X3dyYXAofmFuaW1hbF90eXBlLCBzY2FsZXMgPSAiZnJlZV95IikgKwogIGxhYnMoeCA9ICJEYXRlIiwgeSA9ICJOdW1iZXIgb2YgaW5qdXJpZXMiLCBjb2xvciA9ICJSZWdpb24iKQpgYGAKClFMRCBoYXMgaGFkIGEgbG90IG1vcmUgd2lsZGxpZmUgY2FzZXMsIHN0ZWFkaWx5IGNsaW1iaW5nIHNpbmNlIGFib3V0IDIwMDYuIE5TVyBoYXMgaGFkIGEgYmlnIGRyb3AgaW4gY2F0cyByZWNlbnRseS4gRG9ncyB0b28uIEhvcnNlcyBoYXZlIGdvbmUgdXAgZXZlcnkgcmVnaW9uIGl0IGxvb2tzIGxpa2UuIE5UIGhhcyBoYWQgYSBodWdlIHNwaWtlIGluIGNhdHMgZnJvbSAyMDE1LTIwMTYuCgoKCgoKVGhpcyBvbmUgaGFzIHRoZSBzYW1lIHggYW5kIHksIGJ1dCBpcyBmYWNldGVkIGJhc2VkIG9uIHJlZ2lvbi4gVGhlIGNvbG91cmVkIGxpbmVzIG5vdyByZXByZXNlbnQgdGhlIG91dGNvbWVzLgpgYGB7ciwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0UsIGV2YWw9VFJVRX0KYW5pbWFsX291dGNvbWVzICU+JSAKICBkcm9wX25hKCkgJT4lIAogIGdyb3VwX2J5KHJlZ2lvbiwgb3V0Y29tZSwgeWVhcikgJT4lCiAgc3VtbWFyaXplKHRvdGFsX2luanVyaWVzID0gc3VtKG51bWJlcl9vZl9vY2N1cmVuY2VzKSkgJT4lCiAgdW5ncm91cCgpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gdG90YWxfaW5qdXJpZXMsIGNvbG9yID0gb3V0Y29tZSkpICsKICBnZW9tX2xpbmUoKSArCiAgZmFjZXRfd3JhcCh+cmVnaW9uLCBzY2FsZXMgPSAiZnJlZV95IikgKwogIGxhYnMoeCA9ICJEYXRlIiwgeSA9ICJOdW1iZXIgb2YgaW5qdXJpZXMiLCBjb2xvciA9ICJPdXRjb21lIikKYGBgCgpXQSBpbiAyMDA2IGhhZCBhIGJpZyBpbmNyZWFzZSBpbiBldXRoYW5pemF0aW9ucy4gVklDIGhhcyBoYWQgdGhlaXJzIHN0ZWFkaWx5IGRlY3JlYXNpbmcgb3ZlciB0aW1lLCB0aGlzIGlzIHJlZmxlY3RlZCBhbHNvIGluIE5TVywgVEFTIGFuZCBBQ1QuCgoKCgoKU2FtZSBhcyBiZWZvcmUgd2l0aCBmYWNldGluZyBiYXNlZCBvbiByZWdpb24sIGJ1dCBub3cgdGhlIGNvbG91cmVkIGxpbmVzIHJlcHJlc2VudCB0aGUgdHlwZSBvZiBhbmltYWwgdGhlIFJTUENBIGlzIGRlYWxpbmcgd2l0aC4KYGBge3IsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFLCBldmFsPVRSVUV9CmFuaW1hbF9vdXRjb21lcyAlPiUgCiAgZHJvcF9uYSgpICU+JSAKICBncm91cF9ieShyZWdpb24sIGFuaW1hbF90eXBlLCB5ZWFyKSAlPiUKICBzdW1tYXJpemUodG90YWxfaW5qdXJpZXMgPSBzdW0obnVtYmVyX29mX29jY3VyZW5jZXMpKSAlPiUKICB1bmdyb3VwKCkgJT4lIAogIGdncGxvdChhZXMoeCA9IHllYXIsIHkgPSB0b3RhbF9pbmp1cmllcywgY29sb3IgPSBhbmltYWxfdHlwZSkpICsKICBnZW9tX2xpbmUoKSArCiAgZmFjZXRfd3JhcCh+cmVnaW9uLCBzY2FsZXMgPSAiZnJlZV95IikgKwogIGxhYnMoeCA9ICJEYXRlIiwgeSA9ICJOdW1iZXIgb2YgaW5qdXJpZXMiLCBjb2xvciA9ICJBbmltYWwgVHlwZSIpCmBgYAoKTlQgaGFzIGhhZCBhIGJpZyBzcGlrZSBpbiBkb2dzIGFuZCBjYXRzIGluIHJlY2VudCB5ZWFycy4gV0EgaGFkIGEgYmlnIHNwaWtlIGluIHdpbGRsaWZlIGluIDIwMDUsIGNvcnJlc3BvbmRpbmcgd2l0aCB0aGVpciBzcGlrZSBpbiBldXRoYW5pemF0aW9ucyAtIGNvbW1vbiBzZW5zZSBhbmQgZG9tYWluIGtub3dsZWRnZSB0ZWxsIHVzIHRoZXNlIGFyZSBsaWtlbHkgaGlnaGx5IGNvcnJlbGF0ZWQuIFZJQydzIG51bWJlcnMgaW4gZ2VuZXJhbCBzZWVtIHRvIGJlIGRlY3JlYXNpbmcgb3ZlciB0aW1lLgoKCgoKTG9va2luZyBub3cgc3BlY2lmaWNhbGx5IGF0IGV1dGhhbml6YXRpb25zLCBmYWNldGVkIGJ5IHJlZ2lvbiB3aXRoIHRoZSBsaW5lcyByZXByZXNlbnRpbmcgZXV0aGFuaXphdGlvbnMuCmBgYHtyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRSwgZXZhbD1UUlVFfQphbmltYWxfb3V0Y29tZXMgJT4lIAogIGRyb3BfbmEoKSAlPiUgCiAgZ3JvdXBfYnkocmVnaW9uLCBvdXRjb21lLCB5ZWFyKSAlPiUKICBzdW1tYXJpemUodG90YWxfaW5qdXJpZXMgPSBzdW0obnVtYmVyX29mX29jY3VyZW5jZXMpKSAlPiUKICB1bmdyb3VwKCkgJT4lIAogIGZpbHRlcihvdXRjb21lID09ICJFdXRoYW5pemVkIikgJT4lIAogIGdncGxvdChhZXMoeCA9IHllYXIsIHkgPSB0b3RhbF9pbmp1cmllcywgY29sb3IgPSBvdXRjb21lKSkgKwogIGdlb21fbGluZSgpICsKICBmYWNldF93cmFwKH5yZWdpb24sIHNjYWxlcyA9ICJmcmVlX3kiKSArCiAgbGFicyh4ID0gIkRhdGUiLCB5ID0gIk51bWJlciBvZiBpbmp1cmllcyIsIGNvbG9yID0gIk91dGNvbWUiKQpgYGAKCgoKTm93IHdlIG5vIGxvbmdlciBmYWNldCBieSByZWdpb24uCmBgYHtyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRSwgZXZhbD1UUlVFfQphbmltYWxfb3V0Y29tZXMgJT4lIAogIGRyb3BfbmEoKSAlPiUgCiAgZ3JvdXBfYnkob3V0Y29tZSwgYW5pbWFsX3R5cGUsIHllYXIpICU+JQogIHN1bW1hcml6ZSh0b3RhbF9pbmp1cmllcyA9IHN1bShudW1iZXJfb2Zfb2NjdXJlbmNlcykpICU+JQogIHVuZ3JvdXAoKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgeSA9IHRvdGFsX2luanVyaWVzLCBjb2xvciA9IGFuaW1hbF90eXBlKSkgKwogIGdlb21fbGluZSgpICsKICBmYWNldF93cmFwKH5vdXRjb21lLCBzY2FsZXMgPSAiZnJlZV95IikgKwogIGxhYnMoeCA9ICJEYXRlIiwgeSA9ICJOdW1iZXIgb2YgaW5qdXJpZXMiLCBjb2xvciA9ICJBbmltYWwgVHlwZSIpCgphbmltYWxfb3V0Y29tZXMgJT4lIAogIGRyb3BfbmEoKSAlPiUgCiAgZ3JvdXBfYnkob3V0Y29tZSwgYW5pbWFsX3R5cGUsIHllYXIpICU+JQogIHN1bW1hcml6ZSh0b3RhbF9pbmp1cmllcyA9IHN1bShudW1iZXJfb2Zfb2NjdXJlbmNlcykpICU+JQogIHVuZ3JvdXAoKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgeSA9IHRvdGFsX2luanVyaWVzLCBjb2xvciA9IG91dGNvbWUpKSArCiAgZ2VvbV9saW5lKCkgKwogIGZhY2V0X3dyYXAofmFuaW1hbF90eXBlLCBzY2FsZXMgPSAiZnJlZV95IikgKwogIGxhYnMoeCA9ICJEYXRlIiwgeSA9ICJOdW1iZXIgb2YgaW5qdXJpZXMiLCBjb2xvciA9ICJPdXRjb21lIikKYGBgCgoKYGBge3IsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFLCBldmFsPVRSVUV9CiMgbG9va2luZyBhdCBvbmx5IGV1dGhhbmFzaWEKYW5pbWFsX291dGNvbWVzICU+JSAKICBkcm9wX25hKCkgJT4lIAogIGdyb3VwX2J5KG91dGNvbWUsIGFuaW1hbF90eXBlLCB5ZWFyKSAlPiUKICBzdW1tYXJpemUodG90YWxfaW5qdXJpZXMgPSBzdW0obnVtYmVyX29mX29jY3VyZW5jZXMpKSAlPiUKICB1bmdyb3VwKCkgJT4lIAogIGZpbHRlcihvdXRjb21lID09ICJFdXRoYW5pemVkIikgJT4lIAogIGdncGxvdChhZXMoeCA9IHllYXIsIHkgPSB0b3RhbF9pbmp1cmllcywgY29sb3IgPSBvdXRjb21lKSkgKwogIGdlb21fbGluZSgpICsKICBmYWNldF93cmFwKH5hbmltYWxfdHlwZSwgc2NhbGVzID0gImZyZWVfeSIpICsKICBsYWJzKHggPSAiRGF0ZSIsIHkgPSAiTnVtYmVyIG9mIGluanVyaWVzIiwgY29sb3IgPSAiT3V0Y29tZSIpCgojIGxvb2tpbmcgYXQgb25seSByZWhvbWVkCmFuaW1hbF9vdXRjb21lcyAlPiUgCiAgZHJvcF9uYSgpICU+JSAKICBncm91cF9ieShvdXRjb21lLCBhbmltYWxfdHlwZSwgeWVhcikgJT4lCiAgc3VtbWFyaXplKHRvdGFsX2luanVyaWVzID0gc3VtKG51bWJlcl9vZl9vY2N1cmVuY2VzKSkgJT4lCiAgdW5ncm91cCgpICU+JSAKICBmaWx0ZXIob3V0Y29tZSA9PSAiUmVob21lZCIpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gdG90YWxfaW5qdXJpZXMsIGNvbG9yID0gb3V0Y29tZSkpICsKICBnZW9tX2xpbmUoKSArCiAgZmFjZXRfd3JhcCh+YW5pbWFsX3R5cGUsIHNjYWxlcyA9ICJmcmVlX3kiKSArCiAgbGFicyh4ID0gIkRhdGUiLCB5ID0gIk51bWJlciBvZiBpbmp1cmllcyIsIGNvbG9yID0gIk91dGNvbWUiKQpgYGAKCk9LIHNvIGNhdHMgYW5kIGRvZ3MgaGF2ZSB3YXkgbGVzcyBldXRoYW5pc2F0aW9ucy4gV2lsZGxpZmUgaGFzIGdvbmUgd2F5IHVwISBIb3JzZXMgYXJlIHRvbyBzbWFsbCBhIHNhbXBsZSB0byBiZSBtZWFuaW5nZnVsLiBPdGhlciBhbmltYWxzIGhhdmUgc3Bpa2VkIHRoZW4gZGVjcmVhc2VkLgoKCgpgYGB7ciwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0UsIGV2YWw9VFJVRX0KIyBsb29raW5nIGF0IGJvdGggcmVob21lZCBhbmQgZXV0aGFuaXplZAphbmltYWxfb3V0Y29tZXMgJT4lIAogIGRyb3BfbmEoKSAlPiUgCiAgZ3JvdXBfYnkob3V0Y29tZSwgYW5pbWFsX3R5cGUsIHllYXIpICU+JQogIHN1bW1hcml6ZSh0b3RhbF9pbmp1cmllcyA9IHN1bShudW1iZXJfb2Zfb2NjdXJlbmNlcykpICU+JQogIHVuZ3JvdXAoKSAlPiUgCiAgZmlsdGVyKG91dGNvbWUgPT0gIlJlaG9tZWQiIHwgb3V0Y29tZSA9PSAiRXV0aGFuaXplZCIpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gdG90YWxfaW5qdXJpZXMsIGNvbG9yID0gb3V0Y29tZSkpICsKICBnZW9tX2xpbmUoKSArCiAgZmFjZXRfd3JhcCh+YW5pbWFsX3R5cGUsIHNjYWxlcyA9ICJmcmVlX3kiKSArCiAgbGFicyh4ID0gIkRhdGUiLCB5ID0gIk51bWJlciBvZiBpbmp1cmllcyIsIGNvbG9yID0gIk91dGNvbWUiKQpgYGAKCkxvb2tpbmcgYXQgcmVob21lcyB0byBldXRoYW5pc2F0aW9ucywgd2Ugc2VlIGNhdHMgaGF2ZSBhbiB1cHdhcmQgdHJlbmQgd2l0aCBsZXNzIGV1dGhhbmlzYXRpb25zIGFuZCBtb3JlIHJlaG9tZXMsIHdpdGggZG9ncywgYm90aCBoYXZlIGdvbmUgZG93bi4gUGVyaGFwcyB3aXRoIGRvZ3MgdGhlcmUncyBhIGNvbmZvdW5kaW5nIGZhY3Rvci4gSW4gZmFjdCwgaXQgc2VlbXMgbGlrZSB0aGUgUlNQQ0EgaXMgZGVhbGluZyB3aXRoIGxlc3MgZG9ncyBpbiBnZW5lcmFsLgoKCmBgYHtyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRSwgZXZhbD1UUlVFfQojIGxvb2tpbmcgYXQgYm90aCByZWhvbWVkLCByZWNsYWltZWQgYW5kIGV1dGhhbml6ZWQKYW5pbWFsX291dGNvbWVzICU+JSAKICBkcm9wX25hKCkgJT4lIAogIGdyb3VwX2J5KG91dGNvbWUsIGFuaW1hbF90eXBlLCB5ZWFyKSAlPiUKICBzdW1tYXJpemUodG90YWxfaW5qdXJpZXMgPSBzdW0obnVtYmVyX29mX29jY3VyZW5jZXMpKSAlPiUKICB1bmdyb3VwKCkgJT4lIAogIGZpbHRlcihvdXRjb21lID09ICJSZWhvbWVkIiB8IG91dGNvbWUgPT0gIkV1dGhhbml6ZWQiIHwgb3V0Y29tZSA9PSAiUmVjbGFpbWVkIikgJT4lCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgeSA9IHRvdGFsX2luanVyaWVzLCBjb2xvciA9IG91dGNvbWUpKSArCiAgZ2VvbV9saW5lKCkgKwogIGZhY2V0X3dyYXAofmFuaW1hbF90eXBlLCBzY2FsZXMgPSAiZnJlZV95IikgKwogIGxhYnMoeCA9ICJEYXRlIiwgeSA9ICJOdW1iZXIgb2YgaW5qdXJpZXMiLCBjb2xvciA9ICJPdXRjb21lIikKYGBgCgoKYGBge3IsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFLCBldmFsPVRSVUV9CmFuaW1hbF9vdXRjb21lcyAlPiUgCiAgZHJvcF9uYSgpICU+JSAKICBncm91cF9ieShvdXRjb21lLCBhbmltYWxfdHlwZSwgeWVhcikgJT4lCiAgc3VtbWFyaXplKHRvdGFsX2luanVyaWVzID0gc3VtKG51bWJlcl9vZl9vY2N1cmVuY2VzKSkgJT4lCiAgdW5ncm91cCgpICU+JSAKICBmaWx0ZXIoYW5pbWFsX3R5cGUgPT0gIldpbGRsaWZlIikgJT4lIAogIGdncGxvdChhZXMoeCA9IHllYXIsIHkgPSB0b3RhbF9pbmp1cmllcywgY29sb3IgPSBvdXRjb21lKSkgKwogIGdlb21fbGluZSgpICsKICBsYWJzKHggPSAiRGF0ZSIsIHkgPSAiTnVtYmVyIG9mIGluanVyaWVzIiwgY29sb3IgPSAiT3V0Y29tZSIsIHRpdGxlID0gIldpbGRsaWZlIikKCmFuaW1hbF9vdXRjb21lcyAlPiUgCiAgZHJvcF9uYSgpICU+JSAKICBncm91cF9ieShvdXRjb21lLCBhbmltYWxfdHlwZSwgeWVhciwgcmVnaW9uKSAlPiUKICBzdW1tYXJpemUodG90YWxfaW5qdXJpZXMgPSBzdW0obnVtYmVyX29mX29jY3VyZW5jZXMpKSAlPiUKICB1bmdyb3VwKCkgJT4lIAogIGZpbHRlcihhbmltYWxfdHlwZSA9PSAiV2lsZGxpZmUiICYgb3V0Y29tZSA9PSAiRXV0aGFuaXplZCIpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gdG90YWxfaW5qdXJpZXMsIGNvbG9yID0gb3V0Y29tZSkpICsKICBnZW9tX2xpbmUoKSArCiAgZmFjZXRfd3JhcCh+cmVnaW9uLCBzY2FsZXMgPSAiZnJlZV95IikgKwogIGxhYnMoeCA9ICJEYXRlIiwgeSA9ICJOdW1iZXIgb2YgaW5qdXJpZXMiLCBjb2xvciA9ICJPdXRjb21lIiwgdGl0bGUgPSAiV2lsZGxpZmUiKQpgYGAKCkV1dGhhbml6YXRpb25zIGZvciB3aWxkbGlmZSBoYXZlIG92ZXJhbGwgZ29uZSB1cC4gUXVlZW5zbGFuZCBpcyBza2V3aW5nIHRoZSBkYXRhLCB0aGV5J3ZlIGV1dGhhbml6ZWQgd2F5IG1vcmUhIElzIHRoaXMgbmVjZXNzYXJpbHkgYSBiYWQgdGhpbmc/IEl0IGNvdWxkIGluZGljYXRlIGEgYmlnZ2VyIFJTUENBIHByZXNlbmNlIGluIHRoZSBhcmVhLCBhbmQgbW9yZSB2aWdpbGFuY2UgaW4gcmVnYXJkcyB0byBjb250cm9sbGluZyB0aGUgd2lsZGxpZmUuIAoKCgoKR2VuZXJhbCB0aG91Z2h0czoKCmJpZyBjaGFuZ2UgaW4gMjAwNiBmb3IgV0E7IGN5Y2xvbmUgRW1tYSBNYXJjaCAyMDA2IGNvdWxkJ3ZlIHJlbGVhc2VkIG1hbnkgd2lsZCBhbmltYWxzIGxlYWRpbmcgdG8gaGlnaCBldXRoYW5pemF0aW9ucyAodGhpcyBmb3IgMi5jKQpkaWZmZXJlbnQgdGVycml0b3JpZXMgaGF2ZSBkaWZmZXJlbnQgYXBwcm9hY2hlczsgCgoKCiMjIyA0LiBCdXNpbmVzcyBJbnRlbGxpZ2VuY2Ug4oCTIHVzaW5nIHRoZSBpbnNpZ2h0cyB5b3UgaGF2ZSBmb3VuZCwgY2FuIHlvdSBwcmVkaWN0IGhvdyB0aGlzIG1pZ2h0IGxvb2sgZm9yIHRoZSB1cGNvbWluZyB5ZWFyPwoKCgoKCgpgYGB7cn0KYW5pbWFsX291dGNvbWVzICU+JSAKICBkcm9wX25hKCkgJT4lIAogIGdyb3VwX2J5KHJlZ2lvbiwgb3V0Y29tZSwgeWVhcikgJT4lCiAgc3VtbWFyaXplKHRvdGFsX2luanVyaWVzID0gc3VtKG51bWJlcl9vZl9vY2N1cmVuY2VzKSkgJT4lCiAgdW5ncm91cCgpICU+JSAKICBmaWx0ZXIob3V0Y29tZSA9PSAiRXV0aGFuaXplZCIpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gdG90YWxfaW5qdXJpZXMsIGNvbG9yID0gb3V0Y29tZSkpICsKICBnZW9tX2xpbmUoKSArCiAgZmFjZXRfd3JhcCh+cmVnaW9uLCBzY2FsZXMgPSAiZnJlZV95IikgKwogIGxhYnMoeCA9ICJEYXRlIiwgeSA9ICJOdW1iZXIgb2YgaW5qdXJpZXMiLCBjb2xvciA9ICJPdXRjb21lIikKYGBgCgoKCgoKCgoKCiMjIyBOZXh0IGF0dGVtcHQgZm9yIGEgbW9kZWwKCkkgd2FudCB0byBwcmVkaWN0IHRoZSB0b3RhbCBjYXNlcyBmb3IgQXVzdHJhbGlhLiBXZSB3b24ndCBicmVhayBpdCBkb3duIGJ5IHJlZ2lvbi4gU28gZmlyc3QsIGxldCdzIGdldCBvdXIgc3VtbWFyeSBzdGF0aXN0aWNzIGFuZCBwdXQgaXQgaW4gYSBuZXcgdmFyaWFibGU6CgpgYGB7cn0KYW5pbWFsX291dGNvbWVzICU+JSAKICBkcm9wX25hKCkgJT4lIAogIGdyb3VwX2J5KG91dGNvbWUsIGFuaW1hbF90eXBlLCB5ZWFyLCByZWdpb24pICU+JQogIHN1bW1hcml6ZSh0b3RhbF9pbmp1cmllcyA9IHN1bShudW1iZXJfb2Zfb2NjdXJlbmNlcykpICU+JQogIHVuZ3JvdXAoKSAlPiUgCiAgZmlsdGVyKGFuaW1hbF90eXBlID09ICJDYXRzIiAmIG91dGNvbWUgPT0gIkV1dGhhbml6ZWQiKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgeSA9IHRvdGFsX2luanVyaWVzLCBjb2xvciA9IG91dGNvbWUpKSArCiAgZ2VvbV9saW5lKCkgKwogIGZhY2V0X3dyYXAofnJlZ2lvbiwgc2NhbGVzID0gImZyZWVfeSIpICsKICBsYWJzKHggPSAiRGF0ZSIsIHkgPSAiTnVtYmVyIG9mIGluanVyaWVzIiwgY29sb3IgPSAiT3V0Y29tZSIsIHRpdGxlID0gIkNhdHMiKQpgYGAKCgpgYGB7cn0KYW5pbWFsX291dGNvbWVzICU+JSAKICBkcm9wX25hKCkgJT4lIAogIGdyb3VwX2J5KG91dGNvbWUsIGFuaW1hbF90eXBlLCB5ZWFyKSAlPiUKICBzdW1tYXJpemUodG90YWxfaW5qdXJpZXMgPSBzdW0obnVtYmVyX29mX29jY3VyZW5jZXMpKSAlPiUKICB1bmdyb3VwKCkgJT4lIAogIGZpbHRlcihhbmltYWxfdHlwZSA9PSAiQ2F0cyIgJiBvdXRjb21lID09ICJFdXRoYW5pemVkIikgJT4lIAogIGdncGxvdChhZXMoeCA9IHllYXIsIHkgPSB0b3RhbF9pbmp1cmllcywgY29sb3IgPSBvdXRjb21lKSkgKwogIGdlb21fbGluZSgpICsKICAjZmFjZXRfd3JhcCh+cmVnaW9uLCBzY2FsZXMgPSAiZnJlZV95IikgKwogIGxhYnMoeCA9ICJEYXRlIiwgeSA9ICJOdW1iZXIgb2YgaW5qdXJpZXMiLCBjb2xvciA9ICJPdXRjb21lIiwgdGl0bGUgPSAiQ2F0cyIpCmBgYAoKCmBgYHtyfQp3aWxkbGlmZV90c2JsIDwtIGFuaW1hbF9vdXRjb21lcyAlPiUgCiAgZHJvcF9uYSgpICU+JSAKICBmaWx0ZXIoYW5pbWFsX3R5cGUgPT0gIkNhdHMiICYgb3V0Y29tZSA9PSAiRXV0aGFuaXplZCIpICU+JSAKICBncm91cF9ieSh5ZWFyKSAlPiUgCiAgc3VtbWFyaXNlKHRvdGFsX2V1dGggPSBzdW0obnVtYmVyX29mX29jY3VyZW5jZXMpKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBhc190c2liYmxlKGtleSA9IHllYXIsIGluZGV4ID0gdG90YWxfZXV0aCkKYGBgCgpgYGB7cn0KbGlicmFyeShmYWJsZSkKCiMgRml0IEFSSU1BIG1vZGVsCndpbGRsaWZlX2FyaW1hIDwtIHdpbGRsaWZlX3RzYmwgJT4lIAogIG1vZGVsKHRvdGFsX2V1dGggPSBBUklNQSh0b3RhbF9ldXRoKSkKYGBgCgpgYGB7cn0KIyBHZW5lcmF0ZSBmb3JlY2FzdHMKCiMgQ29udmVydCBBUklNQSBvYmplY3QgdG8gYSB0c2liYmxlIG9iamVjdAp3aWxkbGlmZV90c2JsIDwtIGFzX3RzaWJibGUod2lsZGxpZmVfYXJpbWEsIGtleSA9IHRvdGFsX2V1dGgsIGluZGV4ID0geWVhcikKCiMgR2VuZXJhdGUgZm9yZWNhc3RzCndpbGRsaWZlX2ZvcmVjYXN0IDwtIHdpbGRsaWZlX3RzYmwgJT4lCiAgbW9kZWwoQVJJTUEodG90YWxfZXV0aCkpICU+JSAKICBmb3JlY2FzdChoID0gMzYpCmBgYAoKCgoKCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShmYWJsZSkKbGlicmFyeSh0c2liYmxlKQpsaWJyYXJ5KHRzaWJibGVkYXRhKQojIFdlIGFsc28gbmVlZCB0byB1c2UgdGhlICJ1cmNhIiBwYWNrYWdlIHRvIGJlIGFibGUgdG8gdXNlIHRoZSBBUklNQSBtb2RlbApsaWJyYXJ5KHVyY2EpCmBgYAoKCmBgYHtyfQoKCndpbGRsaWZlX3RzYmwgPC0gYW5pbWFsX291dGNvbWVzICU+JSAKICBkcm9wX25hKCkgJT4lIAogIGZpbHRlcihhbmltYWxfdHlwZSA9PSAiQ2F0cyIgJiBvdXRjb21lID09ICJFdXRoYW5pemVkIikgJT4lIAogIGdyb3VwX2J5KHllYXIpICU+JSAKICBzdW1tYXJpc2UodG90YWxfZXV0aCA9IHN1bShudW1iZXJfb2Zfb2NjdXJlbmNlcykpICU+JSAKICB1bmdyb3VwKCkgJT4lCiAgbXV0YXRlKGRhdGUgPSB5ZWFyICU+JSBhcy5EYXRlKHBhc3RlMCgiLTAxLTAxIikpKSAlPiUgCiAgYXNfdHNpYmJsZShrZXkgPSB5ZWFyLCBpbmRleCA9IGRhdGUpCgp3aWxkbGlmZV9hcmltYSA8LSB3aWxkbGlmZV90c2JsICU+JSAKICBtb2RlbChBUklNQSh0b3RhbF9ldXRoKSkKCndpbGRsaWZlX2ZvcmVjYXN0IDwtIHdpbGRsaWZlX2FyaW1hICU+JSAKICBmb3JlY2FzdChoID0gMzYpCgp3aWxkbGlmZV9mb3JlY2FzdAoKCmBgYAoKYGBge3J9CndpbGRsaWZlX2ZvcmVjYXN0ICU+JSAKICBhdXRvcGxvdCgpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgbWF4KHdpbGRsaWZlX3RzYmwkdG90YWxfZXV0aCwgbmEucm0gPSBUUlVFKSAqIDEuMikpCgpgYGAKCmBgYHtyfQp3aWxkbGlmZV9mY3N0IDwtIHdpbGRsaWZlX2ZvcmVjYXN0ICU+JSAKICBhc190aWJibGUoKSAlPiUgCiAgc2VsZWN0KHllYXIsIC5tZWFuKSAlPiUgCiAgcmVuYW1lKHRvdGFsX2V1dGggPSAubWVhbikKCndpbGRsaWZlX3RzYmxfZmNzdCA8LSB3aWxkbGlmZV90c2JsICU+JSAKICBiaW5kX3Jvd3Mod2lsZGxpZmVfZmNzdCwgLmlkID0gInNvdXJjZSIpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gdG90YWxfZXV0aCwgY29sb3VyID0gc291cmNlKSkgKwogIGdlb21fbGluZSgpICsKICBsYWJzKHRpdGxlID0gIlRvdGFsIEV1dGhhbml6ZWQgQ2F0cyBpbiBBdXN0aW4gQW5pbWFsIENlbnRlciIsCiAgICAgICBzdWJ0aXRsZSA9ICJIaXN0b3JpY2FsIGRhdGEgYW5kIGZvcmVjYXN0cyIsCiAgICAgICB5ID0gIk51bWJlciBvZiBjYXRzIGV1dGhhbml6ZWQiLAogICAgICAgY29sb3IgPSAiU291cmNlIikgKwogIHRoZW1lX21pbmltYWwoKQoKYGBgCgpgYGB7cn0Kd2lsZGxpZmVfZmNzdF90c2JsIDwtIHdpbGRsaWZlX2Zjc3QgJT4lIAogIGFzX3RzaWJibGUoa2V5ID0geWVhciwgaW5kZXggPSB0b3RhbF9ldXRoKSAlPiUgCiAgc2VsZWN0KHllYXIsIHRvdGFsX2V1dGgsIC5tZWFuKQoKZ2dwbG90KHdpbGRsaWZlX2Zjc3RfdHNibCwgYWVzKHggPSB5ZWFyLCB5ID0gdG90YWxfZXV0aCkpICsKICBnZW9tX2xpbmUoKSArCiAgZ2VvbV9saW5lKGFlcyh5ID0gLm1lYW4pLCBjb2xvciA9ICJibHVlIikgKwogIGxhYnModGl0bGUgPSAiRm9yZWNhc3Qgb2YgRXV0aGFuaXplZCBDYXRzIGluIEF1c3RpbiBBbmltYWwgQ2VudGVyIiwKICAgICAgIHggPSAiWWVhciIsCiAgICAgICB5ID0gIlRvdGFsIEV1dGhhbml6ZWQgQ2F0cyIpICsKICB0aGVtZV9taW5pbWFsKCkKCmBgYAoKYGBge3J9CgojIENyZWF0ZSB0c2liYmxlCndpbGRsaWZlX3RzYmwgPC0gYW5pbWFsX291dGNvbWVzICU+JSAKICBkcm9wX25hKCkgJT4lIAogIGZpbHRlcihhbmltYWxfdHlwZSA9PSAiQ2F0cyIgJiBvdXRjb21lID09ICJFdXRoYW5pemVkIikgJT4lIAogIGdyb3VwX2J5KHllYXIpICU+JSAKICBzdW1tYXJpc2UodG90YWxfZXV0aCA9IHN1bShudW1iZXJfb2Zfb2NjdXJlbmNlcykpICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIGFzX3RzaWJibGUoaW5kZXggPSB5ZWFyKQoKIyBGaXQgQVJJTUEgbW9kZWwKd2lsZGxpZmVfYXJpbWEgPC0gd2lsZGxpZmVfdHNibCAlPiUgCiAgbW9kZWwoQVJJTUEodG90YWxfZXV0aCkpCgojIEdlbmVyYXRlIGZvcmVjYXN0cwp3aWxkbGlmZV9mY3N0IDwtIHdpbGRsaWZlX2FyaW1hICU+JSAKICBmb3JlY2FzdChoID0gMzYpCgojIEFkZCBzb3VyY2UgY29sdW1uIHRvIGZvcmVjYXN0CndpbGRsaWZlX2Zjc3QgJT4lCiAgbXV0YXRlKHNvdXJjZSA9ICJmb3JlY2FzdCIpICU+JQogIHNlbGVjdChzb3VyY2UsIHllYXIsIC5tZWFuKSAlPiUKICBiaW5kX3Jvd3Mod2lsZGxpZmVfdHNibCAlPiUgYXNfdGliYmxlKCkgJT4lIG11dGF0ZShzb3VyY2UgPSAiYWN0dWFsIikpICU+JQogIAogICMgUGxvdCB0aGUgYWN0dWFscyBhbmQgZm9yZWNhc3RzCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgeSA9IC5tZWFuLCBjb2xvciA9IHNvdXJjZSkpICsKICBnZW9tX2xpbmUoKSArCiAgbGFicyh5ID0gIlRvdGFsIEV1dGhhbml6ZWQgQ2F0cyIpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiYWN0dWFsIiA9ICJibGFjayIsICJmb3JlY2FzdCIgPSAicmVkIikpICsKICB0aGVtZV9taW5pbWFsKCkKCmBgYAoKYGBge3J9CgojIGNyZWF0ZSB0c2liYmxlCndpbGRsaWZlX3RzYmwgPC0gYW5pbWFsX291dGNvbWVzICU+JSAKICBkcm9wX25hKCkgJT4lIAogIGZpbHRlcihhbmltYWxfdHlwZSA9PSAiQ2F0cyIgJiBvdXRjb21lID09ICJFdXRoYW5pemVkIikgJT4lIAogIGdyb3VwX2J5KHllYXIpICU+JSAKICBzdW1tYXJpc2UodG90YWxfZXV0aCA9IHN1bShudW1iZXJfb2Zfb2NjdXJlbmNlcykpICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIGFzX3RzaWJibGUoaW5kZXggPSB5ZWFyKQoKIyBmaWxsIGdhcHMKd2lsZGxpZmVfdHNibF9maWxsZWQgPC0gd2lsZGxpZmVfdHNibCAlPiUgZmlsbF9nYXBzKCkKCiMgZml0IG1vZGVsIGFuZCBnZW5lcmF0ZSBmb3JlY2FzdAp3aWxkbGlmZV9hcmltYSA8LSB3aWxkbGlmZV90c2JsX2ZpbGxlZCAlPiUgCiAgbW9kZWwoQVJJTUEodG90YWxfZXV0aCkpCgp3aWxkbGlmZV9mb3JlY2FzdCA8LSB3aWxkbGlmZV9hcmltYSAlPiUgCiAgZm9yZWNhc3QoaCA9IDM2KQoKIyBwbG90IGZvcmVjYXN0CndpbGRsaWZlX2Zjc3QgPC0gd2lsZGxpZmVfZm9yZWNhc3QgJT4lIAogIGFzX3RpYmJsZSgpICU+JSAKICBtdXRhdGUoc291cmNlID0gImZvcmVjYXN0IikKCmdncGxvdCgpICsKICBnZW9tX2xpbmUoZGF0YSA9IHdpbGRsaWZlX3RzYmxfZmlsbGVkLCBhZXMoeCA9IHllYXIsIHkgPSB0b3RhbF9ldXRoKSkgKwogIGdlb21fbGluZShkYXRhID0gd2lsZGxpZmVfZmNzdCwgYWVzKHggPSB5ZWFyLCB5ID0gLm1lYW4sIGNvbG9yID0gc291cmNlKSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJibGFjayIsICJyZWQiKSkgKwogIGxhYnModGl0bGUgPSAiQ2F0cyBFdXRoYW5pemVkIE92ZXIgVGltZSIsCiAgICAgICB4ID0gIlllYXIiLAogICAgICAgeSA9ICJOdW1iZXIgb2YgQ2F0cyBFdXRoYW5pemVkIikKCmBgYAoKYGBge3J9CgojIENvbnZlcnQgdG8gdHNpYmJsZSBvYmplY3QKd2lsZGxpZmVfdHNibCA8LSBhbmltYWxfb3V0Y29tZXMgJT4lCiAgZHJvcF9uYSgpICU+JQogIGZpbHRlcihhbmltYWxfdHlwZSA9PSAiQ2F0cyIgJiBvdXRjb21lID09ICJFdXRoYW5pemVkIikgJT4lCiAgZ3JvdXBfYnkoeWVhcikgJT4lCiAgc3VtbWFyaXNlKHRvdGFsX2V1dGggPSBzdW0obnVtYmVyX29mX29jY3VyZW5jZXMpKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgYXNfdHNpYmJsZShpbmRleCA9IHllYXIpCgojIENvbnZlcnQgdG8gdGltZSBzZXJpZXMgb2JqZWN0CndpbGRsaWZlX3RzIDwtIHRzKHdpbGRsaWZlX3RzYmwkdG90YWxfZXV0aCkKCiMgRml0IEFSSU1BIG1vZGVsCndpbGRsaWZlX2FyaW1hIDwtIHdpbGRsaWZlX3RzICU+JQogIG1vZGVsKEFSSU1BKQoKIyBHZW5lcmF0ZSBmb3JlY2FzdHMKd2lsZGxpZmVfZm9yZWNhc3QgPC0gd2lsZGxpZmVfYXJpbWEgJT4lCiAgZm9yZWNhc3QoaCA9IDM2KQoKIyBDb21iaW5lIG9ic2VydmVkIGRhdGEgYW5kIGZvcmVjYXN0cwp3aWxkbGlmZV9mY3N0IDwtIGJpbmRfcm93cygKICBhc190aWJibGUod2lsZGxpZmVfdHNibCksCiAgYXNfdGliYmxlKHdpbGRsaWZlX2ZvcmVjYXN0KSAlPiUgCiAgICByZW5hbWUodG90YWxfZXV0aCA9IC5tZWFuKQopICU+JSAKICBtdXRhdGUoc291cmNlID0gaWZfZWxzZShpcy5uYSh0b3RhbF9ldXRoKSwgIkZvcmVjYXN0IiwgIk9ic2VydmVkIikpCgojIFBsb3QgcmVzdWx0cwp3aWxkbGlmZV9mY3N0ICU+JQogIGdncGxvdChhZXMoeCA9IHllYXIsIHkgPSB0b3RhbF9ldXRoLCBjb2xvciA9IHNvdXJjZSkpICsKICBnZW9tX2xpbmUoKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoImJsdWUiLCAicmVkIikpICsKICBsYWJzKHggPSAiWWVhciIsIHkgPSAiVG90YWwgRXV0aGFuaXplZCBDYXRzIiwgY29sb3IgPSAiU291cmNlIiwgCiAgICAgICB0aXRsZSA9ICJUb3RhbCBFdXRoYW5pemVkIENhdHMgaW4gQXVzdGluLCBUWCIpICsKICB0aGVtZV9taW5pbWFsKCkKCmBgYApgYGB7cn0KCiMgQ29udmVydCB0cyBvYmplY3QgdG8gdHNpYmJsZQp3aWxkbGlmZV90c2JsIDwtIGFzX3RzaWJibGUod2lsZGxpZmVfdHMsIGluZGV4ID0gInllYXIiKQoKIyBGaXQgQVJJTUEgbW9kZWwgdG8gdHNpYmJsZQp3aWxkbGlmZV9hcmltYSA8LSB3aWxkbGlmZV90c2JsICU+JSAKICBtb2RlbChBUklNQSh2YWx1ZSkpCgojIEdlbmVyYXRlIGZvcmVjYXN0cwp3aWxkbGlmZV9mb3JlY2FzdCA8LSB3aWxkbGlmZV9hcmltYSAlPiUgCiAgZm9yZWNhc3QoaCA9IDM2KQoKIyBDb252ZXJ0IGZvcmVjYXN0IHRvIGEgdHNpYmJsZQp3aWxkbGlmZV9mY3N0IDwtIGFzX3RzaWJibGUod2lsZGxpZmVfZm9yZWNhc3QsIGtleSA9ICJ5ZWFyIikKCiMgUGxvdCB0aGUgZm9yZWNhc3QKd2lsZGxpZmVfZmNzdCAlPiUKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gLm1lYW4sIGNvbG9yID0gc291cmNlKSkgKwogIGdlb21fbGluZSgpCgpgYGAKCmBgYHtyfQoKIyBDb252ZXJ0IHRzIG9iamVjdCB0byB0c2liYmxlCndpbGRsaWZlX3RzYmwgPC0gYXNfdHNpYmJsZSh3aWxkbGlmZV90cywgaW5kZXggPSAieWVhciIpCgojIEZpdCBBUklNQSBtb2RlbCB0byB0c2liYmxlCndpbGRsaWZlX2FyaW1hIDwtIHdpbGRsaWZlX3RzYmwgJT4lIAogIG1vZGVsKEFSSU1BKHZhbHVlKSkKCiMgR2VuZXJhdGUgZm9yZWNhc3RzCndpbGRsaWZlX2ZvcmVjYXN0IDwtIHdpbGRsaWZlX2FyaW1hICU+JSAKICBmb3JlY2FzdChoID0gMzYpCgojIENvbnZlcnQgZm9yZWNhc3QgdG8gYSB0c2liYmxlCndpbGRsaWZlX2Zjc3QgPC0gYXNfdHNpYmJsZSh3aWxkbGlmZV9mb3JlY2FzdCwga2V5ID0gInllYXIiKQoKIyBQbG90IHRoZSBmb3JlY2FzdAp3aWxkbGlmZV9mY3N0ICU+JQogIGdncGxvdChhZXMoeCA9IGluZGV4LCB5ID0gLm1lYW4sIGNvbG9yID0gLm1vZGVsKSkgKwogIGdlb21fbGluZSgpCgoKYGBgCgpgYGB7cn0KbmFtZXMod2lsZGxpZmVfZmNzdCkKCmxpYnJhcnkobHVicmlkYXRlKQpgYGAKCiMjIwoKYGBge3J9CiMgZ3JvdXBpbmcgdGhlIGRhdGEgYW5kIGNyZWF0aW5nIGEgdmFyaWFibGUKYW5pbWFsX2NvbXBsYWludHNfZ3JvdXBlZCA8LSBhbmltYWxfY29tcGxhaW50cyAlPiUgCiAgZ3JvdXBfYnkoZGF0ZV9yZWNlaXZlZCkgJT4lIAogIHN1bW1hcmlzZShjb3VudCA9IG4oKSkgJT4lIAogIGFycmFuZ2UoZGF0ZV9yZWNlaXZlZCkKCm15dHMgPC0gdHMoYW5pbWFsX2NvbXBsYWludHNfZ3JvdXBlZCRjb3VudCwgZnJlcXVlbmN5ID0gMTIsIHN0YXJ0ID0gYyh5ZWFyKGFuaW1hbF9jb21wbGFpbnRzX2dyb3VwZWQkZGF0ZV9yZWNlaXZlZFsxXSksIG1vbnRoKGFuaW1hbF9jb21wbGFpbnRzX2dyb3VwZWQkZGF0ZV9yZWNlaXZlZFsxXSkpKQoKbXlmb3JlY2FzdCA8LSBmb3JlY2FzdChhdXRvLmFyaW1hKG15dHMpLCBoID0gMjQpCgoKcGxvdChteWZvcmVjYXN0LCBtYWluID0gIkZvcmVjYXN0ZWQgdmFsdWVzIikKCmBgYAoKCmBgYHtyfQpteXRzX2ZvcmVjYXN0IDwtIGZ1bmN0aW9uKG15dHMsIGgsIGludGVydmFsKSB7CiAgbGlicmFyeShmb3JlY2FzdCkKICAKICAjIFNldCB0aGUgYXBwcm9wcmlhdGUgdGltZSBpbnRlcnZhbCBmb3IgdGhlIGZvcmVjYXN0IGhvcml6b24KICBpbnRlcnZhbCA8LSBzd2l0Y2goaW50ZXJ2YWwsCiAgICAgICAgICAgICAgICAgICAgICJkYXkiID0gImRheXMiLAogICAgICAgICAgICAgICAgICAgICAiaG91ciIgPSAiaG91cnMiLAogICAgICAgICAgICAgICAgICAgICAibWludXRlIiA9ICJtaW5zIiwKICAgICAgICAgICAgICAgICAgICAgInNlY29uZCIgPSAic2VjcyIpCiAgCiAgIyBDcmVhdGUgdGhlIGZvcmVjYXN0CiAgbXlmb3JlY2FzdCA8LSBmb3JlY2FzdChteXRzLCBoID0gMjQsIGxldmVsID0gYyg4MCwgOTUpLCAKICAgICAgICAgICAgICAgICAgICAgICB4cmVnID0gbXlkdW1taWVzLCAKICAgICAgICAgICAgICAgICAgICAgICBsYW1iZGEgPSBOVUxMLCBiaWFzYWRqID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICBmYW4gPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICAgaW50ZXJ2YWwgPSAid2VlayIpCgogIAogICMgUHJpbnQgdGhlIGZvcmVjYXN0IHRhYmxlCiAgcHJpbnQobXlmb3JlY2FzdCkKICAKICAjIFBsb3QgdGhlIGZvcmVjYXN0CiAgYXV0b3Bsb3QobXlmb3JlY2FzdCkKfQoKYGBgCgpgYGB7cn0KcHJpbnQoaW50ZXJ2YWwpCnByaW50KGNsYXNzKGludGVydmFsKSkKcHJpbnQobGVuZ3RoKGludGVydmFsKSkKYGBgCgpgYGB7cn0KIyBDcmVhdGUgYSBzZXF1ZW5jZSBvZiBkYXRlcyBmb3IgdGhlIG5leHQgMjQgbW9udGhzCmRhdGVzIDwtIHNlcShhcy5EYXRlKCIyMDIzLTAzLTAxIiksIGJ5ID0gIm1vbnRoIiwgbGVuZ3RoLm91dCA9IDI0KQoKIyBDcmVhdGUgYSB0aW1lIHNlcmllcyBvYmplY3Qgd2l0aCByYW5kb20gdmFsdWVzIGZvciBkZW1vbnN0cmF0aW9uIHB1cnBvc2VzCnZhbHVlcyA8LSBybm9ybSgyNCkKbXl0cyA8LSB0cyh2YWx1ZXMsIHN0YXJ0ID0gYyh5ZWFyKGRhdGVzWzFdKSwgbW9udGgoZGF0ZXNbMV0pKSwgZnJlcXVlbmN5ID0gMTIpCgojIFBsb3QgdGhlIHRpbWUgc2VyaWVzCnBsb3QobXl0cykKCiMgRm9yZWNhc3QgdGhlIG5leHQgMjQgbW9udGhzCmxpYnJhcnkoZm9yZWNhc3QpCm15Zm9yZWNhc3QgPC0gZm9yZWNhc3QobXl0cywgaCA9IDI0KQoKIyBQbG90IHRoZSBmb3JlY2FzdGVkIHZhbHVlcwpwbG90KG15Zm9yZWNhc3QpCgpgYGAKCgoKIyMjIEFub3RoZXIsIEZJTkFMIGF0dGVtcHQKClRoaXMgaXMgcXVpdGUgZGlmZmljdWx0IGluZGVlZC4gTGV0J3MgdHJ5IGdvIHNsb3dseSB1c2luZyB0aGUgbm90ZXMsIGJ1aWxkIGl0IGJpdCBieSBiaXQuCgpgYGB7cn0KbGlicmFyeShmZWFzdHMpCgphbmltYWxfY29tcGxhaW50c19ncm91cGVkIDwtIGFuaW1hbF9jb21wbGFpbnRzX2dyb3VwZWQgJT4lIAogIGRyb3BfbmEoKQpgYGAKClNvIGFsbCB3ZSB3YW5uYSBkbywgaXMgcGxvdCB0aGUgbmV4dCBmZXcgeWVhcnMsIGFuZCBzZWUgd2hhdCBpdCB3aWxsIGxvb2sgbGlrZSBvbiB0aGUgZ3JhcGguIE5vdGhpbmcgbmVlZHMgdG8gYmUgdG9vIGZhbmN5LiBXZSB3aWxsIGtlZXAgaXQgc2ltcGxlLCBjcmVhdGUgYSBzaW1wbGUgbW9kZWwuIFRoZW4gcGxvdCB0aGlzLiBPSy4KClNvIGZpcnN0LCBpdCBuZWVkcyB0byBiZSB0c2liYmxlLgpgYGB7cn0KYW5pbWFsX2NvbXBsYWludHNfdHNpYmJsZSA8LSBhc190c2liYmxlKGFuaW1hbF9jb21wbGFpbnRzX2dyb3VwZWQsIGluZGV4ID0gZGF0ZV9yZWNlaXZlZCkKCmFuaW1hbF9jb21wbGFpbnRzX3RzaWJibGUgPC0gYW5pbWFsX2NvbXBsYWludHNfdHNpYmJsZSAlPiUgCiAgbXV0YXRlKGRhdGVfcmVjZWl2ZWQgPSB0c2liYmxlOjp5ZWFybW9udGgoZGF0ZV9yZWNlaXZlZCkpICU+JSAKICBtdXRhdGUoY291bnQgPSBhcy5kb3VibGUoY291bnQpKQpgYGAKCkl0IGhhcyBub3cgYmVlbiBjb252ZXJ0ZWQgdG8gYSB0c2liYmxlLCB3aXRoIGRhdGVfcmVjZWl2ZWQgYXMgdGhlIGluZGV4LiBBcyBpdCBjb250YWlucyBvbmx5IGEgc2luZ2xlIHRpbWUgc2VyaWVzLCBhIGtleSBzaG91bGQgbm90IGJlIG5lY2Vzc2FyeS4KCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShmYWJsZSkKbGlicmFyeSh0c2liYmxlKQpsaWJyYXJ5KHRzaWJibGVkYXRhKQojIFdlIGFsc28gbmVlZCB0byB1c2UgdGhlICJ1cmNhIiBwYWNrYWdlIHRvIGJlIGFibGUgdG8gdXNlIHRoZSBBUklNQSBtb2RlbApsaWJyYXJ5KHVyY2EpCmBgYAoKV2UgbG9hZCBpbiBhbGwgcGFja2FnZXMganVzdCB0byBiZSAxMDAlIHN1cmUgdGhleSBhcmUgbG9hZGVkLiAKCmBgYHtyfQojIG5vIG5lZWQgdG8gZGVzZWxlY3QgdmFyaWFibGVzOyB3ZSBhbHJlYWR5IGhhdmUgdGhlIG9ubHkgMiB3ZSB3aWxsIG5lZWQuCgojIG5leHQsIHdlIHdpbGwgdXNlIGF1dG9wbG90CmF1dG9wbG90KGFuaW1hbF9jb21wbGFpbnRzX3RzaWJibGUpCmBgYAoKT3VyIGRhdGEgaXMgdGhlcmUuIE5vdywgd2Ugd2lsbCBmaXQgYSBtb2RlbC4KCmBgYHtyfQpsaWJyYXJ5KHB1cnJyKQoKZml0IDwtIGFuaW1hbF9jb21wbGFpbnRzX3RzaWJibGUgJT4lCiAgbW9kZWwoCiAgICBzbmFpdmUgPSBTTkFJVkUoY291bnQpLAogICAgbWVhbl9tb2RlbCA9IE1FQU4oY291bnQpLAogICAgYXJpbWEgPSBBUklNQShjb3VudCkKICApCmZpdAoKIyBmaXQgJT4lIAojICAgZG1hcCh1bmxpc3QpCmBgYAoKSGVyZSBpcyBvdXIgbWFibGUsIGFsc28gY2FsbGVkIG1vZGVsIHRhYmxlLiBFYWNoIGNlbGwgY29ycmVzcG9uZHMgdG8gYSBmaXR0ZWQgbW9kZWwuIE5vdywgd2Ugd2lsbCBjYWxjdWxhdGUgc29tZSBmb3JlY2FzdHMgdXNpbmcgb3VyIG1vZGVsLgoKYGBge3J9CmZvcmVjYXN0XzEgPC0gZml0ICU+JQogIGZhYmxldG9vbHM6OmZvcmVjYXN0KGggPSAzNikKZm9yZWNhc3RfMQpgYGAKCk9LLCBsb29raW5nIGdvb2Qgc28gZmFyLgoKYGBge3J9CmZvcmVjYXN0XzEgJT4lCiAgYXV0b3Bsb3QoYW5pbWFsX2NvbXBsYWludHNfdHNpYmJsZSkKYGBgCgpMZXQncyBtYWtlIG91ciBtb2RlbCBsb29rIHByZXR0eSBhbmQgaGF2ZSBsZXNzIGNsdXR0ZXIKCmBgYHtyfQpmb3JlY2FzdF8xICU+JQogIGZpbHRlcigubW9kZWwgPT0gImFyaW1hIikgJT4lIAogIGF1dG9wbG90KGFuaW1hbF9jb21wbGFpbnRzX3RzaWJibGUsIGxldmVsID0gOTUpICsKICBzY2FsZV94X3llYXJtb250aChkYXRlX2JyZWFrcyA9ICI2IG1vbnRocyIsIGRhdGVfbGFiZWxzID0gIiViICV5IikgKyAKICBsYWJzKHRpdGxlID0gIlRvd25zdmlsbGUgQ29tcGxhaW50IENhbGxzIHdpdGggUHJlZGljdGlvbiIsCiAgICAgICB4ID0gIlRpbWUiLAogICAgICAgeSA9ICJOdW1iZXIgb2YgQ2FsbHMiKSArCiAgdGhlbWVfZWNvbm9taXN0KCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIHZqdXN0ID0gMSwgZmFtaWx5ID0gIm1vbm8iLCBmYWNlID0gImJvbGQiLCBzaXplID0gNyksCiAgICAgICAgI2F4aXMudGlja3MueCA9IAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dCh2anVzdCA9IDMuMiksCiAgICAgICAgdGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gIm1vbm8iLCBmYWNlID0gImJvbGQiKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC40KSwKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgICAgICAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gYXMuRGF0ZSgiMjAxNC0wNi0wMSIpLCB4bWF4ID0gYXMuRGF0ZSgiMjAxNC0wOC0wMSIpLCB5bWluID0gLUluZiwgeW1heCA9IEluZiwgZmlsbCA9ICJncmF5NzAiLCBhbHBoYSA9IDAuMykgKwogICAgICAgIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IGFzLkRhdGUoIjIwMTUtMDYtMDEiKSwgeG1heCA9IGFzLkRhdGUoIjIwMTUtMDgtMDEiKSwgeW1pbiA9IC1JbmYsIHltYXggPSBJbmYsIGZpbGwgPSAiZ3JheTcwIiwgYWxwaGEgPSAwLjMpICsKICAgICAgICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSBhcy5EYXRlKCIyMDE2LTA2LTAxIiksIHhtYXggPSBhcy5EYXRlKCIyMDE2LTA4LTAxIiksIHltaW4gPSAtSW5mLCB5bWF4ID0gSW5mLCBmaWxsID0gImdyYXk3MCIsIGFscGhhID0gMC4zKSArCiAgICAgICAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gYXMuRGF0ZSgiMjAxNy0wNi0wMSIpLCB4bWF4ID0gYXMuRGF0ZSgiMjAxNy0wOC0wMSIpLCB5bWluID0gLUluZiwgeW1heCA9IEluZiwgZmlsbCA9ICJncmF5NzAiLCBhbHBoYSA9IDAuMykgKwogICAgICAgIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IGFzLkRhdGUoIjIwMTgtMDYtMDEiKSwgeG1heCA9IGFzLkRhdGUoIjIwMTgtMDgtMDEiKSwgeW1pbiA9IC1JbmYsIHltYXggPSBJbmYsIGZpbGwgPSAiZ3JheTcwIiwgYWxwaGEgPSAwLjMpICsKICAgICAgICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSBhcy5EYXRlKCIyMDE5LTA2LTAxIiksIHhtYXggPSBhcy5EYXRlKCIyMDE5LTA4LTAxIiksIHltaW4gPSAtSW5mLCB5bWF4ID0gSW5mLCBmaWxsID0gImdyYXk3MCIsIGFscGhhID0gMC4zKSArCiAgICAgICAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gYXMuRGF0ZSgiMjAyMC0wNi0wMSIpLCB4bWF4ID0gYXMuRGF0ZSgiMjAyMC0wOC0wMSIpLCB5bWluID0gLUluZiwgeW1heCA9IEluZiwgZmlsbCA9ICJncmF5NzAiLCBhbHBoYSA9IDAuMykgKwogICAgICAgIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IGFzLkRhdGUoIjIwMjEtMDYtMDEiKSwgeG1heCA9IGFzLkRhdGUoIjIwMjEtMDgtMDEiKSwgeW1pbiA9IC1JbmYsIHltYXggPSBJbmYsIGZpbGwgPSAiZ3JheTcwIiwgYWxwaGEgPSAwLjMpICsKICAgICAgICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSBhcy5EYXRlKCIyMDIyLTA2LTAxIiksIHhtYXggPSBhcy5EYXRlKCIyMDIyLTA4LTAxIiksIHltaW4gPSAtSW5mLCB5bWF4ID0gSW5mLCBmaWxsID0gImdyYXk3MCIsIGFscGhhID0gMC4zKSArCiAgICAgICAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gYXMuRGF0ZSgiMjAyMy0wNi0wMSIpLCB4bWF4ID0gYXMuRGF0ZSgiMjAyMy0wOC0wMSIpLCB5bWluID0gLUluZiwgeW1heCA9IEluZiwgZmlsbCA9ICJncmF5NzAiLCBhbHBoYSA9IDAuMykKICAgICAgICAgICAgICAgICAgICAgICAgCmBgYAoKU28gSSB3YXMgYWxzbyB0YXNrZWQgd2l0aCBjcmVhdGluZyBhIG1vZGVsLCB0byBwcmVkaWN0IGhvdyB0aGluZ3MgbWlnaHQgbG9vayBmb3IgdGhlIG5leHQgZmV3IHllYXJzLiBJIGZvY3VzZWQgc3BlY2lmaWNhbGx5IG9uIHRoZSBUb3duc3ZpbGxlIGRhdGEsIGFzIHRoaXMgd2FzIG1vc3Qgc3VpdGFibGUgZm9yIGZvcmVjYXN0aW5nLiBJIHVzZWQgc29tZXRoaW5nIGNhbGxlZCB0aGUgIkFSSU1BIiBtb2RlbCwgdGhlIGlubmVyIHdvcmtpbmdzIG9mIHdoaWNoIGFyZSBxdWl0ZSBjb21wbGljYXRlZCwgYnV0IGJhc2ljYWxseSBpdCBwcmVkaWN0cyB0aGUgZnV0dXJlIGJhc2VkIG9uIHRoZSBwYXN0LCBhbmQgaXMgcXVpdGUgZ29vZCB3aGVuIGl0IGNvbWVzIHRvIHNlYXNvbmFsIGRhdGEgbGlrZSBJIGhhdmUgaGVyZS4gVGhlIGJsdWUgbGluZSBpcyB0aGUgcHJlZGljdGlvbiwgYW5kIHRoZSBsaWdodCBibHVlIGFyZWEgeW91IHNlZSBoaWdobGlnaHRlZCBhcm91bmQgaXQgaXMgdGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWwuIFRoaW5rIG9mIHRoaXMgbGlrZSBhIG1hcmdpbiBvZiBlcnJvciwgYW5kIGl0IGJhc2ljYWxseSBtZWFucyB0aGF0IDk1JSBvZiB0aGUgdGltZSwgb3VyIG1vZGVsIHdpbGwgcHJlZGljdCByZXN1bHRzIGluIHRoaXMgYXJlYS4KClRoaXMgbW9kZWwgc3VnZ2VzdHMgdGhhdCByb3VnaGx5IHRoZSBzYW1lIHBhdHRlcm4gd2lsbCBjb250aW51ZSBhcyBiZWZvcmUsIHdpdGggZmFpcmx5IHN0ZWFkeSB2b2x1bWUgb2YgY2FsbHMgYW5kIGhpZ2ggcGVha3MgaW4gV2ludGVyLiBCdXQgYmVhciBpbiBtaW5kIHRoaXMgbW9kZWwgaXMgcXVpdGUgbGltaXRlZCBhbmQgc2hvdWxkbid0IGJlIHRha2VuIGFzIGZhY3Q7IGZvciBleGFtcGxlLCBpdCBkb2Vzbid0IHRha2UgaW50byBhY2NvdW50IG5hdHVyYWwgZGlzYXN0ZXJzIGFuZCBvdGhlciBldmVudHMgd2hpY2ggY291bGQgY2F1c2UgYW4gaW5jcmVhc2UgaW4gY29tcGxhaW50IGNhbGxzLgoKCgojIyMgRG9jdW1lbnRhdGlvbiBub3RlCgpGaXggb3IgZGlzY3VzcyB0aGUgZXJyb3Igb2YgTlQgYW5kIE5TVyBzd2FwcGluZyBmb3IgMjAxNi0yMDE4CgpgYGB7cn0KYW5pbWFsX291dGNvbWVzICU+JSAKICBtdXRhdGUocmVnaW9uID0gaWYoKSkKYGBgCgo=